Consolidate ARRAY_SIZE macro; remove one unneeded global var (walter harms <wharms...
[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 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
105
106 static char optlist[NOPTS];
107
108 #define eflag optlist[0]
109 #define fflag optlist[1]
110 #define Iflag optlist[2]
111 #define iflag optlist[3]
112 #define mflag optlist[4]
113 #define nflag optlist[5]
114 #define sflag optlist[6]
115 #define xflag optlist[7]
116 #define vflag optlist[8]
117 #define Cflag optlist[9]
118 #define aflag optlist[10]
119 #define bflag optlist[11]
120 #define uflag optlist[12]
121 #define viflag optlist[13]
122 #if DEBUG
123 #define nolog optlist[14]
124 #define debug optlist[15]
125 #endif
126
127
128 /* ============ Misc data */
129
130 static char nullstr[1];                /* zero length string */
131 static const char homestr[] = "HOME";
132 static const char snlfmt[] = "%s\n";
133 static const char illnum[] = "Illegal number: %s";
134
135 static char *minusc;                   /* argument to -c option */
136
137 static int isloginsh;
138 /* pid of main shell */
139 static int rootpid;
140 /* shell level: 0 for the main shell, 1 for its children, and so on */
141 static int shlvl;
142 #define rootshell (!shlvl)
143 /* trap handler commands */
144 static char *trap[NSIG];
145 /* current value of signal */
146 static char sigmode[NSIG - 1];
147 /* indicates specified signal received */
148 static char gotsig[NSIG - 1];
149 static char *arg0; /* value of $0 */
150
151
152 /* ============ Interrupts / exceptions */
153
154 /*
155  * We enclose jmp_buf in a structure so that we can declare pointers to
156  * jump locations.  The global variable handler contains the location to
157  * jump to when an exception occurs, and the global variable exception
158  * contains a code identifying the exception.  To implement nested
159  * exception handlers, the user should save the value of handler on entry
160  * to an inner scope, set handler to point to a jmploc structure for the
161  * inner scope, and restore handler on exit from the scope.
162  */
163 struct jmploc {
164         jmp_buf loc;
165 };
166 static struct jmploc *exception_handler;
167 static int exception;
168 /* exceptions */
169 #define EXINT 0         /* SIGINT received */
170 #define EXERROR 1       /* a generic error */
171 #define EXSHELLPROC 2   /* execute a shell procedure */
172 #define EXEXEC 3        /* command execution failed */
173 #define EXEXIT 4        /* exit the shell */
174 #define EXSIG 5         /* trapped signal in wait(1) */
175 static volatile int suppressint;
176 static volatile sig_atomic_t intpending;
177 /* do we generate EXSIG events */
178 static int exsig;
179 /* last pending signal */
180 static volatile sig_atomic_t pendingsig;
181
182 /*
183  * Sigmode records the current value of the signal handlers for the various
184  * modes.  A value of zero means that the current handler is not known.
185  * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
186  */
187
188 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
189 #define S_CATCH 2               /* signal is caught */
190 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
191 #define S_HARD_IGN 4            /* signal is ignored permenantly */
192 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
193
194 /*
195  * These macros allow the user to suspend the handling of interrupt signals
196  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
197  * much more efficient and portable.  (But hacking the kernel is so much
198  * more fun than worrying about efficiency and portability. :-))
199  */
200 #define INT_OFF \
201         do { \
202                 suppressint++; \
203                 xbarrier(); \
204         } while (0)
205
206 /*
207  * Called to raise an exception.  Since C doesn't include exceptions, we
208  * just do a longjmp to the exception handler.  The type of exception is
209  * stored in the global variable "exception".
210  */
211 static void raise_exception(int) ATTRIBUTE_NORETURN;
212 static void
213 raise_exception(int e)
214 {
215 #if DEBUG
216         if (exception_handler == NULL)
217                 abort();
218 #endif
219         INT_OFF;
220         exception = e;
221         longjmp(exception_handler->loc, 1);
222 }
223
224 /*
225  * Called from trap.c when a SIGINT is received.  (If the user specifies
226  * that SIGINT is to be trapped or ignored using the trap builtin, then
227  * this routine is not called.)  Suppressint is nonzero when interrupts
228  * are held using the INT_OFF macro.  (The test for iflag is just
229  * defensive programming.)
230  */
231 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
232 static void
233 raise_interrupt(void)
234 {
235         int i;
236         sigset_t mask;
237
238         intpending = 0;
239         /* Signal is not automatically re-enabled after it is raised,
240          * do it ourself */
241         sigemptyset(&mask);
242         sigprocmask(SIG_SETMASK, &mask, 0);
243         /* pendingsig = 0; - now done in onsig() */
244
245         i = EXSIG;
246         if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
247                 if (!(rootshell && iflag)) {
248                         signal(SIGINT, SIG_DFL);
249                         raise(SIGINT);
250                 }
251                 i = EXINT;
252         }
253         raise_exception(i);
254         /* NOTREACHED */
255 }
256
257 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
258 static void
259 int_on(void)
260 {
261         if (--suppressint == 0 && intpending) {
262                 raise_interrupt();
263         }
264 }
265 #define INT_ON int_on()
266 static void
267 force_int_on(void)
268 {
269         suppressint = 0;
270         if (intpending)
271                 raise_interrupt();
272 }
273 #define FORCE_INT_ON force_int_on()
274 #else
275 #define INT_ON \
276         do { \
277                 xbarrier(); \
278                 if (--suppressint == 0 && intpending) \
279                         raise_interrupt(); \
280         } while (0)
281 #define FORCE_INT_ON \
282         do { \
283                 xbarrier(); \
284                 suppressint = 0; \
285                 if (intpending) \
286                         raise_interrupt(); \
287         } while (0)
288 #endif /* ASH_OPTIMIZE_FOR_SIZE */
289
290 #define SAVE_INT(v) ((v) = suppressint)
291
292 #define RESTORE_INT(v) \
293         do { \
294                 xbarrier(); \
295                 suppressint = (v); \
296                 if (suppressint == 0 && intpending) \
297                         raise_interrupt(); \
298         } while (0)
299
300 #define EXSIGON \
301         do { \
302                 exsig++; \
303                 xbarrier(); \
304                 if (pendingsig) \
305                         raise_exception(EXSIG); \
306         } while (0)
307 /* EXSIG is turned off by evalbltin(). */
308
309 /*
310  * Ignore a signal. Only one usage site - in forkchild()
311  */
312 static void
313 ignoresig(int signo)
314 {
315         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
316                 signal(signo, SIG_IGN);
317         }
318         sigmode[signo - 1] = S_HARD_IGN;
319 }
320
321 /*
322  * Signal handler. Only one usage site - in setsignal()
323  */
324 static void
325 onsig(int signo)
326 {
327         gotsig[signo - 1] = 1;
328         pendingsig = signo;
329
330         if (exsig || (signo == SIGINT && !trap[SIGINT])) {
331                 if (!suppressint) {
332                         pendingsig = 0;
333                         raise_interrupt();
334                 }
335                 intpending = 1;
336         }
337 }
338
339
340 /* ============ Stdout/stderr output */
341
342 static void
343 outstr(const char *p, FILE *file)
344 {
345         INT_OFF;
346         fputs(p, file);
347         INT_ON;
348 }
349
350 static void
351 flush_stdout_stderr(void)
352 {
353         INT_OFF;
354         fflush(stdout);
355         fflush(stderr);
356         INT_ON;
357 }
358
359 static void
360 flush_stderr(void)
361 {
362         INT_OFF;
363         fflush(stderr);
364         INT_ON;
365 }
366
367 static void
368 outcslow(int c, FILE *dest)
369 {
370         INT_OFF;
371         putc(c, dest);
372         fflush(dest);
373         INT_ON;
374 }
375
376 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
377 static int
378 out1fmt(const char *fmt, ...)
379 {
380         va_list ap;
381         int r;
382
383         INT_OFF;
384         va_start(ap, fmt);
385         r = vprintf(fmt, ap);
386         va_end(ap);
387         INT_ON;
388         return r;
389 }
390
391 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
392 static int
393 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
394 {
395         va_list ap;
396         int ret;
397
398         va_start(ap, fmt);
399         INT_OFF;
400         ret = vsnprintf(outbuf, length, fmt, ap);
401         va_end(ap);
402         INT_ON;
403         return ret;
404 }
405
406 static void
407 out1str(const char *p)
408 {
409         outstr(p, stdout);
410 }
411
412 static void
413 out2str(const char *p)
414 {
415         outstr(p, stderr);
416         flush_stderr();
417 }
418
419
420 /* ============ Parser structures */
421
422 /* control characters in argument strings */
423 #define CTLESC '\201'           /* escape next character */
424 #define CTLVAR '\202'           /* variable defn */
425 #define CTLENDVAR '\203'
426 #define CTLBACKQ '\204'
427 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
428 /*      CTLBACKQ | CTLQUOTE == '\205' */
429 #define CTLARI  '\206'          /* arithmetic expression */
430 #define CTLENDARI '\207'
431 #define CTLQUOTEMARK '\210'
432
433 /* variable substitution byte (follows CTLVAR) */
434 #define VSTYPE  0x0f            /* type of variable substitution */
435 #define VSNUL   0x10            /* colon--treat the empty string as unset */
436 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
437
438 /* values of VSTYPE field */
439 #define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
440 #define VSMINUS         0x2             /* ${var-text} */
441 #define VSPLUS          0x3             /* ${var+text} */
442 #define VSQUESTION      0x4             /* ${var?message} */
443 #define VSASSIGN        0x5             /* ${var=text} */
444 #define VSTRIMRIGHT     0x6             /* ${var%pattern} */
445 #define VSTRIMRIGHTMAX  0x7             /* ${var%%pattern} */
446 #define VSTRIMLEFT      0x8             /* ${var#pattern} */
447 #define VSTRIMLEFTMAX   0x9             /* ${var##pattern} */
448 #define VSLENGTH        0xa             /* ${#var} */
449
450 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
451
452 #define NCMD 0
453 #define NPIPE 1
454 #define NREDIR 2
455 #define NBACKGND 3
456 #define NSUBSHELL 4
457 #define NAND 5
458 #define NOR 6
459 #define NSEMI 7
460 #define NIF 8
461 #define NWHILE 9
462 #define NUNTIL 10
463 #define NFOR 11
464 #define NCASE 12
465 #define NCLIST 13
466 #define NDEFUN 14
467 #define NARG 15
468 #define NTO 16
469 #define NCLOBBER 17
470 #define NFROM 18
471 #define NFROMTO 19
472 #define NAPPEND 20
473 #define NTOFD 21
474 #define NFROMFD 22
475 #define NHERE 23
476 #define NXHERE 24
477 #define NNOT 25
478
479 union node;
480
481 struct ncmd {
482         int type;
483         union node *assign;
484         union node *args;
485         union node *redirect;
486 };
487
488 struct npipe {
489         int type;
490         int backgnd;
491         struct nodelist *cmdlist;
492 };
493
494 struct nredir {
495         int type;
496         union node *n;
497         union node *redirect;
498 };
499
500 struct nbinary {
501         int type;
502         union node *ch1;
503         union node *ch2;
504 };
505
506 struct nif {
507         int type;
508         union node *test;
509         union node *ifpart;
510         union node *elsepart;
511 };
512
513 struct nfor {
514         int type;
515         union node *args;
516         union node *body;
517         char *var;
518 };
519
520 struct ncase {
521         int type;
522         union node *expr;
523         union node *cases;
524 };
525
526 struct nclist {
527         int type;
528         union node *next;
529         union node *pattern;
530         union node *body;
531 };
532
533 struct narg {
534         int type;
535         union node *next;
536         char *text;
537         struct nodelist *backquote;
538 };
539
540 struct nfile {
541         int type;
542         union node *next;
543         int fd;
544         union node *fname;
545         char *expfname;
546 };
547
548 struct ndup {
549         int type;
550         union node *next;
551         int fd;
552         int dupfd;
553         union node *vname;
554 };
555
556 struct nhere {
557         int type;
558         union node *next;
559         int fd;
560         union node *doc;
561 };
562
563 struct nnot {
564         int type;
565         union node *com;
566 };
567
568 union node {
569         int type;
570         struct ncmd ncmd;
571         struct npipe npipe;
572         struct nredir nredir;
573         struct nbinary nbinary;
574         struct nif nif;
575         struct nfor nfor;
576         struct ncase ncase;
577         struct nclist nclist;
578         struct narg narg;
579         struct nfile nfile;
580         struct ndup ndup;
581         struct nhere nhere;
582         struct nnot nnot;
583 };
584
585 struct nodelist {
586         struct nodelist *next;
587         union node *n;
588 };
589
590 struct funcnode {
591         int count;
592         union node n;
593 };
594
595 /*
596  * Free a parse tree.
597  */
598 static void
599 freefunc(struct funcnode *f)
600 {
601         if (f && --f->count < 0)
602                 free(f);
603 }
604
605
606 /* ============ Debugging output */
607
608 #if DEBUG
609
610 static FILE *tracefile;
611
612 static void
613 trace_printf(const char *fmt, ...)
614 {
615         va_list va;
616
617         if (debug != 1)
618                 return;
619         va_start(va, fmt);
620         vfprintf(tracefile, fmt, va);
621         va_end(va);
622 }
623
624 static void
625 trace_vprintf(const char *fmt, va_list va)
626 {
627         if (debug != 1)
628                 return;
629         vfprintf(tracefile, fmt, va);
630 }
631
632 static void
633 trace_puts(const char *s)
634 {
635         if (debug != 1)
636                 return;
637         fputs(s, tracefile);
638 }
639
640 static void
641 trace_puts_quoted(char *s)
642 {
643         char *p;
644         char c;
645
646         if (debug != 1)
647                 return;
648         putc('"', tracefile);
649         for (p = s; *p; p++) {
650                 switch (*p) {
651                 case '\n':  c = 'n';  goto backslash;
652                 case '\t':  c = 't';  goto backslash;
653                 case '\r':  c = 'r';  goto backslash;
654                 case '"':  c = '"';  goto backslash;
655                 case '\\':  c = '\\';  goto backslash;
656                 case CTLESC:  c = 'e';  goto backslash;
657                 case CTLVAR:  c = 'v';  goto backslash;
658                 case CTLVAR+CTLQUOTE:  c = 'V'; goto backslash;
659                 case CTLBACKQ:  c = 'q';  goto backslash;
660                 case CTLBACKQ+CTLQUOTE:  c = 'Q'; goto backslash;
661  backslash:
662                         putc('\\', tracefile);
663                         putc(c, tracefile);
664                         break;
665                 default:
666                         if (*p >= ' ' && *p <= '~')
667                                 putc(*p, tracefile);
668                         else {
669                                 putc('\\', tracefile);
670                                 putc(*p >> 6 & 03, tracefile);
671                                 putc(*p >> 3 & 07, tracefile);
672                                 putc(*p & 07, tracefile);
673                         }
674                         break;
675                 }
676         }
677         putc('"', tracefile);
678 }
679
680 static void
681 trace_puts_args(char **ap)
682 {
683         if (debug != 1)
684                 return;
685         if (!*ap)
686                 return;
687         while (1) {
688                 trace_puts_quoted(*ap);
689                 if (!*++ap) {
690                         putc('\n', tracefile);
691                         break;
692                 }
693                 putc(' ', tracefile);
694         }
695 }
696
697 static void
698 opentrace(void)
699 {
700         char s[100];
701 #ifdef O_APPEND
702         int flags;
703 #endif
704
705         if (debug != 1) {
706                 if (tracefile)
707                         fflush(tracefile);
708                 /* leave open because libedit might be using it */
709                 return;
710         }
711         strcpy(s, "./trace");
712         if (tracefile) {
713                 if (!freopen(s, "a", tracefile)) {
714                         fprintf(stderr, "Can't re-open %s\n", s);
715                         debug = 0;
716                         return;
717                 }
718         } else {
719                 tracefile = fopen(s, "a");
720                 if (tracefile == NULL) {
721                         fprintf(stderr, "Can't open %s\n", s);
722                         debug = 0;
723                         return;
724                 }
725         }
726 #ifdef O_APPEND
727         flags = fcntl(fileno(tracefile), F_GETFL, 0);
728         if (flags >= 0)
729                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
730 #endif
731         setlinebuf(tracefile);
732         fputs("\nTracing started.\n", tracefile);
733 }
734
735 static void
736 indent(int amount, char *pfx, FILE *fp)
737 {
738         int i;
739
740         for (i = 0; i < amount; i++) {
741                 if (pfx && i == amount - 1)
742                         fputs(pfx, fp);
743                 putc('\t', fp);
744         }
745 }
746
747 /* little circular references here... */
748 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
749
750 static void
751 sharg(union node *arg, FILE *fp)
752 {
753         char *p;
754         struct nodelist *bqlist;
755         int subtype;
756
757         if (arg->type != NARG) {
758                 out1fmt("<node type %d>\n", arg->type);
759                 abort();
760         }
761         bqlist = arg->narg.backquote;
762         for (p = arg->narg.text; *p; p++) {
763                 switch (*p) {
764                 case CTLESC:
765                         putc(*++p, fp);
766                         break;
767                 case CTLVAR:
768                         putc('$', fp);
769                         putc('{', fp);
770                         subtype = *++p;
771                         if (subtype == VSLENGTH)
772                                 putc('#', fp);
773
774                         while (*p != '=')
775                                 putc(*p++, fp);
776
777                         if (subtype & VSNUL)
778                                 putc(':', fp);
779
780                         switch (subtype & VSTYPE) {
781                         case VSNORMAL:
782                                 putc('}', fp);
783                                 break;
784                         case VSMINUS:
785                                 putc('-', fp);
786                                 break;
787                         case VSPLUS:
788                                 putc('+', fp);
789                                 break;
790                         case VSQUESTION:
791                                 putc('?', fp);
792                                 break;
793                         case VSASSIGN:
794                                 putc('=', fp);
795                                 break;
796                         case VSTRIMLEFT:
797                                 putc('#', fp);
798                                 break;
799                         case VSTRIMLEFTMAX:
800                                 putc('#', fp);
801                                 putc('#', fp);
802                                 break;
803                         case VSTRIMRIGHT:
804                                 putc('%', fp);
805                                 break;
806                         case VSTRIMRIGHTMAX:
807                                 putc('%', fp);
808                                 putc('%', fp);
809                                 break;
810                         case VSLENGTH:
811                                 break;
812                         default:
813                                 out1fmt("<subtype %d>", subtype);
814                         }
815                         break;
816                 case CTLENDVAR:
817                         putc('}', fp);
818                         break;
819                 case CTLBACKQ:
820                 case CTLBACKQ|CTLQUOTE:
821                         putc('$', fp);
822                         putc('(', fp);
823                         shtree(bqlist->n, -1, NULL, fp);
824                         putc(')', fp);
825                         break;
826                 default:
827                         putc(*p, fp);
828                         break;
829                 }
830         }
831 }
832
833 static void
834 shcmd(union node *cmd, FILE *fp)
835 {
836         union node *np;
837         int first;
838         const char *s;
839         int dftfd;
840
841         first = 1;
842         for (np = cmd->ncmd.args; np; np = np->narg.next) {
843                 if (! first)
844                         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 + ARRAY_SIZE(varinit);
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                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
6880                         sizeof(tokname_array[0]), 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
8098 #define COMMANDCMD (builtintab + 5 + \
8099         2 * ENABLE_ASH_BUILTIN_TEST + \
8100         ENABLE_ASH_ALIAS + \
8101         ENABLE_ASH_JOB_CONTROL)
8102 #define EXECCMD (builtintab + 7 + \
8103         2 * ENABLE_ASH_BUILTIN_TEST + \
8104         ENABLE_ASH_ALIAS + \
8105         ENABLE_ASH_JOB_CONTROL + \
8106         ENABLE_ASH_CMDCMD + \
8107         ENABLE_ASH_BUILTIN_ECHO)
8108
8109 /*
8110  * Search the table of builtin commands.
8111  */
8112 static struct builtincmd *
8113 find_builtin(const char *name)
8114 {
8115         struct builtincmd *bp;
8116
8117         bp = bsearch(
8118                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8119                 pstrcmp
8120         );
8121         return bp;
8122 }
8123
8124 /*
8125  * Execute a simple command.
8126  */
8127 static int back_exitstatus; /* exit status of backquoted command */
8128 static int
8129 isassignment(const char *p)
8130 {
8131         const char *q = endofname(p);
8132         if (p == q)
8133                 return 0;
8134         return *q == '=';
8135 }
8136 static int
8137 bltincmd(int argc, char **argv)
8138 {
8139         /* Preserve exitstatus of a previous possible redirection
8140          * as POSIX mandates */
8141         return back_exitstatus;
8142 }
8143 static void
8144 evalcommand(union node *cmd, int flags)
8145 {
8146         static const struct builtincmd bltin = {
8147                 "\0\0", bltincmd
8148         };
8149         struct stackmark smark;
8150         union node *argp;
8151         struct arglist arglist;
8152         struct arglist varlist;
8153         char **argv;
8154         int argc;
8155         const struct strlist *sp;
8156         struct cmdentry cmdentry;
8157         struct job *jp;
8158         char *lastarg;
8159         const char *path;
8160         int spclbltin;
8161         int cmd_is_exec;
8162         int status;
8163         char **nargv;
8164         struct builtincmd *bcmd;
8165         int pseudovarflag = 0;
8166
8167         /* First expand the arguments. */
8168         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8169         setstackmark(&smark);
8170         back_exitstatus = 0;
8171
8172         cmdentry.cmdtype = CMDBUILTIN;
8173         cmdentry.u.cmd = &bltin;
8174         varlist.lastp = &varlist.list;
8175         *varlist.lastp = NULL;
8176         arglist.lastp = &arglist.list;
8177         *arglist.lastp = NULL;
8178
8179         argc = 0;
8180         if (cmd->ncmd.args) {
8181                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8182                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8183         }
8184
8185         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8186                 struct strlist **spp;
8187
8188                 spp = arglist.lastp;
8189                 if (pseudovarflag && isassignment(argp->narg.text))
8190                         expandarg(argp, &arglist, EXP_VARTILDE);
8191                 else
8192                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8193
8194                 for (sp = *spp; sp; sp = sp->next)
8195                         argc++;
8196         }
8197
8198         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8199         for (sp = arglist.list; sp; sp = sp->next) {
8200                 TRACE(("evalcommand arg: %s\n", sp->text));
8201                 *nargv++ = sp->text;
8202         }
8203         *nargv = NULL;
8204
8205         lastarg = NULL;
8206         if (iflag && funcnest == 0 && argc > 0)
8207                 lastarg = nargv[-1];
8208
8209         preverrout_fd = 2;
8210         expredir(cmd->ncmd.redirect);
8211         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8212
8213         path = vpath.text;
8214         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8215                 struct strlist **spp;
8216                 char *p;
8217
8218                 spp = varlist.lastp;
8219                 expandarg(argp, &varlist, EXP_VARTILDE);
8220
8221                 /*
8222                  * Modify the command lookup path, if a PATH= assignment
8223                  * is present
8224                  */
8225                 p = (*spp)->text;
8226                 if (varequal(p, path))
8227                         path = p;
8228         }
8229
8230         /* Print the command if xflag is set. */
8231         if (xflag) {
8232                 int n;
8233                 const char *p = " %s";
8234
8235                 p++;
8236                 dprintf(preverrout_fd, p, expandstr(ps4val()));
8237
8238                 sp = varlist.list;
8239                 for (n = 0; n < 2; n++) {
8240                         while (sp) {
8241                                 dprintf(preverrout_fd, p, sp->text);
8242                                 sp = sp->next;
8243                                 if (*p == '%') {
8244                                         p--;
8245                                 }
8246                         }
8247                         sp = arglist.list;
8248                 }
8249                 full_write(preverrout_fd, "\n", 1);
8250         }
8251
8252         cmd_is_exec = 0;
8253         spclbltin = -1;
8254
8255         /* Now locate the command. */
8256         if (argc) {
8257                 const char *oldpath;
8258                 int cmd_flag = DO_ERR;
8259
8260                 path += 5;
8261                 oldpath = path;
8262                 for (;;) {
8263                         find_command(argv[0], &cmdentry, cmd_flag, path);
8264                         if (cmdentry.cmdtype == CMDUNKNOWN) {
8265                                 status = 127;
8266                                 flush_stderr();
8267                                 goto bail;
8268                         }
8269
8270                         /* implement bltin and command here */
8271                         if (cmdentry.cmdtype != CMDBUILTIN)
8272                                 break;
8273                         if (spclbltin < 0)
8274                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8275                         if (cmdentry.u.cmd == EXECCMD)
8276                                 cmd_is_exec++;
8277 #if ENABLE_ASH_CMDCMD
8278                         if (cmdentry.u.cmd == COMMANDCMD) {
8279                                 path = oldpath;
8280                                 nargv = parse_command_args(argv, &path);
8281                                 if (!nargv)
8282                                         break;
8283                                 argc -= nargv - argv;
8284                                 argv = nargv;
8285                                 cmd_flag |= DO_NOFUNC;
8286                         } else
8287 #endif
8288                                 break;
8289                 }
8290         }
8291
8292         if (status) {
8293                 /* We have a redirection error. */
8294                 if (spclbltin > 0)
8295                         raise_exception(EXERROR);
8296  bail:
8297                 exitstatus = status;
8298                 goto out;
8299         }
8300
8301         /* Execute the command. */
8302         switch (cmdentry.cmdtype) {
8303         default:
8304                 /* Fork off a child process if necessary. */
8305                 if (!(flags & EV_EXIT) || trap[0]) {
8306                         INT_OFF;
8307                         jp = makejob(cmd, 1);
8308                         if (forkshell(jp, cmd, FORK_FG) != 0) {
8309                                 exitstatus = waitforjob(jp);
8310                                 INT_ON;
8311                                 break;
8312                         }
8313                         FORCE_INT_ON;
8314                 }
8315                 listsetvar(varlist.list, VEXPORT|VSTACK);
8316                 shellexec(argv, path, cmdentry.u.index);
8317                 /* NOTREACHED */
8318
8319         case CMDBUILTIN:
8320                 cmdenviron = varlist.list;
8321                 if (cmdenviron) {
8322                         struct strlist *list = cmdenviron;
8323                         int i = VNOSET;
8324                         if (spclbltin > 0 || argc == 0) {
8325                                 i = 0;
8326                                 if (cmd_is_exec && argc > 1)
8327                                         i = VEXPORT;
8328                         }
8329                         listsetvar(list, i);
8330                 }
8331                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8332                         int exit_status;
8333                         int i, j;
8334
8335                         i = exception;
8336                         if (i == EXEXIT)
8337                                 goto raise;
8338
8339                         exit_status = 2;
8340                         j = 0;
8341                         if (i == EXINT)
8342                                 j = SIGINT;
8343                         if (i == EXSIG)
8344                                 j = pendingsig;
8345                         if (j)
8346                                 exit_status = j + 128;
8347                         exitstatus = exit_status;
8348
8349                         if (i == EXINT || spclbltin > 0) {
8350  raise:
8351                                 longjmp(exception_handler->loc, 1);
8352                         }
8353                         FORCE_INT_ON;
8354                 }
8355                 break;
8356
8357         case CMDFUNCTION:
8358                 listsetvar(varlist.list, 0);
8359                 if (evalfun(cmdentry.u.func, argc, argv, flags))
8360                         goto raise;
8361                 break;
8362         }
8363
8364  out:
8365         popredir(cmd_is_exec);
8366         if (lastarg)
8367                 /* dsl: I think this is intended to be used to support
8368                  * '_' in 'vi' command mode during line editing...
8369                  * However I implemented that within libedit itself.
8370                  */
8371                 setvar("_", lastarg, 0);
8372         popstackmark(&smark);
8373 }
8374
8375 static int
8376 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8377 {
8378         char *volatile savecmdname;
8379         struct jmploc *volatile savehandler;
8380         struct jmploc jmploc;
8381         int i;
8382
8383         savecmdname = commandname;
8384         i = setjmp(jmploc.loc);
8385         if (i)
8386                 goto cmddone;
8387         savehandler = exception_handler;
8388         exception_handler = &jmploc;
8389         commandname = argv[0];
8390         argptr = argv + 1;
8391         optptr = NULL;                  /* initialize nextopt */
8392         exitstatus = (*cmd->builtin)(argc, argv);
8393         flush_stdout_stderr();
8394  cmddone:
8395         exitstatus |= ferror(stdout);
8396         clearerr(stdout);
8397         commandname = savecmdname;
8398         exsig = 0;
8399         exception_handler = savehandler;
8400
8401         return i;
8402 }
8403
8404 static int
8405 goodname(const char *p)
8406 {
8407         return !*endofname(p);
8408 }
8409
8410
8411 /*
8412  * Search for a command.  This is called before we fork so that the
8413  * location of the command will be available in the parent as well as
8414  * the child.  The check for "goodname" is an overly conservative
8415  * check that the name will not be subject to expansion.
8416  */
8417 static void
8418 prehash(union node *n)
8419 {
8420         struct cmdentry entry;
8421
8422         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8423                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8424 }
8425
8426
8427 /* ============ Builtin commands
8428  *
8429  * Builtin commands whose functions are closely tied to evaluation
8430  * are implemented here.
8431  */
8432
8433 /*
8434  * Handle break and continue commands.  Break, continue, and return are
8435  * all handled by setting the evalskip flag.  The evaluation routines
8436  * above all check this flag, and if it is set they start skipping
8437  * commands rather than executing them.  The variable skipcount is
8438  * the number of loops to break/continue, or the number of function
8439  * levels to return.  (The latter is always 1.)  It should probably
8440  * be an error to break out of more loops than exist, but it isn't
8441  * in the standard shell so we don't make it one here.
8442  */
8443 static int
8444 breakcmd(int argc, char **argv)
8445 {
8446         int n = argc > 1 ? number(argv[1]) : 1;
8447
8448         if (n <= 0)
8449                 ash_msg_and_raise_error(illnum, argv[1]);
8450         if (n > loopnest)
8451                 n = loopnest;
8452         if (n > 0) {
8453                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8454                 skipcount = n;
8455         }
8456         return 0;
8457 }
8458
8459
8460 /* ============ input.c
8461  *
8462  * This implements the input routines used by the parser.
8463  */
8464
8465 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
8466
8467 enum {
8468         INPUT_PUSH_FILE = 1,
8469         INPUT_NOFILE_OK = 2,
8470 };
8471
8472 /*
8473  * NEOF is returned by parsecmd when it encounters an end of file.  It
8474  * must be distinct from NULL, so we use the address of a variable that
8475  * happens to be handy.
8476  */
8477 static int plinno = 1;                  /* input line number */
8478 /* number of characters left in input buffer */
8479 static int parsenleft;                  /* copy of parsefile->nleft */
8480 static int parselleft;                  /* copy of parsefile->lleft */
8481 /* next character in input buffer */
8482 static char *parsenextc;                /* copy of parsefile->nextc */
8483
8484 static int checkkwd;
8485 /* values of checkkwd variable */
8486 #define CHKALIAS        0x1
8487 #define CHKKWD          0x2
8488 #define CHKNL           0x4
8489
8490 static void
8491 popstring(void)
8492 {
8493         struct strpush *sp = parsefile->strpush;
8494
8495         INT_OFF;
8496 #if ENABLE_ASH_ALIAS
8497         if (sp->ap) {
8498                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8499                         checkkwd |= CHKALIAS;
8500                 }
8501                 if (sp->string != sp->ap->val) {
8502                         free(sp->string);
8503                 }
8504                 sp->ap->flag &= ~ALIASINUSE;
8505                 if (sp->ap->flag & ALIASDEAD) {
8506                         unalias(sp->ap->name);
8507                 }
8508         }
8509 #endif
8510         parsenextc = sp->prevstring;
8511         parsenleft = sp->prevnleft;
8512 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8513         parsefile->strpush = sp->prev;
8514         if (sp != &(parsefile->basestrpush))
8515                 free(sp);
8516         INT_ON;
8517 }
8518
8519 static int
8520 preadfd(void)
8521 {
8522         int nr;
8523         char *buf =  parsefile->buf;
8524         parsenextc = buf;
8525
8526  retry:
8527 #if ENABLE_FEATURE_EDITING
8528         if (!iflag || parsefile->fd)
8529                 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8530         else {
8531 #if ENABLE_FEATURE_TAB_COMPLETION
8532                 line_input_state->path_lookup = pathval();
8533 #endif
8534                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8535                 if (nr == 0) {
8536                         /* Ctrl+C pressed */
8537                         if (trap[SIGINT]) {
8538                                 buf[0] = '\n';
8539                                 buf[1] = '\0';
8540                                 raise(SIGINT);
8541                                 return 1;
8542                         }
8543                         goto retry;
8544                 }
8545                 if (nr < 0 && errno == 0) {
8546                         /* Ctrl+D presend */
8547                         nr = 0;
8548                 }
8549         }
8550 #else
8551         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8552 #endif
8553
8554         if (nr < 0) {
8555                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8556                         int flags = fcntl(0, F_GETFL, 0);
8557                         if (flags >= 0 && flags & O_NONBLOCK) {
8558                                 flags &=~ O_NONBLOCK;
8559                                 if (fcntl(0, F_SETFL, flags) >= 0) {
8560                                         out2str("sh: turning off NDELAY mode\n");
8561                                         goto retry;
8562                                 }
8563                         }
8564                 }
8565         }
8566         return nr;
8567 }
8568
8569 /*
8570  * Refill the input buffer and return the next input character:
8571  *
8572  * 1) If a string was pushed back on the input, pop it;
8573  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8574  *    from a string so we can't refill the buffer, return EOF.
8575  * 3) If the is more stuff in this buffer, use it else call read to fill it.
8576  * 4) Process input up to the next newline, deleting nul characters.
8577  */
8578 static int
8579 preadbuffer(void)
8580 {
8581         char *q;
8582         int more;
8583         char savec;
8584
8585         while (parsefile->strpush) {
8586 #if ENABLE_ASH_ALIAS
8587                 if (parsenleft == -1 && parsefile->strpush->ap &&
8588                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8589                         return PEOA;
8590                 }
8591 #endif
8592                 popstring();
8593                 if (--parsenleft >= 0)
8594                         return signed_char2int(*parsenextc++);
8595         }
8596         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8597                 return PEOF;
8598         flush_stdout_stderr();
8599
8600         more = parselleft;
8601         if (more <= 0) {
8602  again:
8603                 more = preadfd();
8604                 if (more <= 0) {
8605                         parselleft = parsenleft = EOF_NLEFT;
8606                         return PEOF;
8607                 }
8608         }
8609
8610         q = parsenextc;
8611
8612         /* delete nul characters */
8613         for (;;) {
8614                 int c;
8615
8616                 more--;
8617                 c = *q;
8618
8619                 if (!c)
8620                         memmove(q, q + 1, more);
8621                 else {
8622                         q++;
8623                         if (c == '\n') {
8624                                 parsenleft = q - parsenextc - 1;
8625                                 break;
8626                         }
8627                 }
8628
8629                 if (more <= 0) {
8630                         parsenleft = q - parsenextc - 1;
8631                         if (parsenleft < 0)
8632                                 goto again;
8633                         break;
8634                 }
8635         }
8636         parselleft = more;
8637
8638         savec = *q;
8639         *q = '\0';
8640
8641         if (vflag) {
8642                 out2str(parsenextc);
8643         }
8644
8645         *q = savec;
8646
8647         return signed_char2int(*parsenextc++);
8648 }
8649
8650 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8651 static int
8652 pgetc(void)
8653 {
8654         return pgetc_as_macro();
8655 }
8656
8657 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8658 #define pgetc_macro() pgetc()
8659 #else
8660 #define pgetc_macro() pgetc_as_macro()
8661 #endif
8662
8663 /*
8664  * Same as pgetc(), but ignores PEOA.
8665  */
8666 #if ENABLE_ASH_ALIAS
8667 static int
8668 pgetc2(void)
8669 {
8670         int c;
8671
8672         do {
8673                 c = pgetc_macro();
8674         } while (c == PEOA);
8675         return c;
8676 }
8677 #else
8678 static int
8679 pgetc2(void)
8680 {
8681         return pgetc_macro();
8682 }
8683 #endif
8684
8685 /*
8686  * Read a line from the script.
8687  */
8688 static char *
8689 pfgets(char *line, int len)
8690 {
8691         char *p = line;
8692         int nleft = len;
8693         int c;
8694
8695         while (--nleft > 0) {
8696                 c = pgetc2();
8697                 if (c == PEOF) {
8698                         if (p == line)
8699                                 return NULL;
8700                         break;
8701                 }
8702                 *p++ = c;
8703                 if (c == '\n')
8704                         break;
8705         }
8706         *p = '\0';
8707         return line;
8708 }
8709
8710 /*
8711  * Undo the last call to pgetc.  Only one character may be pushed back.
8712  * PEOF may be pushed back.
8713  */
8714 static void
8715 pungetc(void)
8716 {
8717         parsenleft++;
8718         parsenextc--;
8719 }
8720
8721 /*
8722  * Push a string back onto the input at this current parsefile level.
8723  * We handle aliases this way.
8724  */
8725 static void
8726 pushstring(char *s, void *ap)
8727 {
8728         struct strpush *sp;
8729         size_t len;
8730
8731         len = strlen(s);
8732         INT_OFF;
8733 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8734         if (parsefile->strpush) {
8735                 sp = ckmalloc(sizeof(struct strpush));
8736                 sp->prev = parsefile->strpush;
8737                 parsefile->strpush = sp;
8738         } else
8739                 sp = parsefile->strpush = &(parsefile->basestrpush);
8740         sp->prevstring = parsenextc;
8741         sp->prevnleft = parsenleft;
8742 #if ENABLE_ASH_ALIAS
8743         sp->ap = (struct alias *)ap;
8744         if (ap) {
8745                 ((struct alias *)ap)->flag |= ALIASINUSE;
8746                 sp->string = s;
8747         }
8748 #endif
8749         parsenextc = s;
8750         parsenleft = len;
8751         INT_ON;
8752 }
8753
8754 /*
8755  * To handle the "." command, a stack of input files is used.  Pushfile
8756  * adds a new entry to the stack and popfile restores the previous level.
8757  */
8758 static void
8759 pushfile(void)
8760 {
8761         struct parsefile *pf;
8762
8763         parsefile->nleft = parsenleft;
8764         parsefile->lleft = parselleft;
8765         parsefile->nextc = parsenextc;
8766         parsefile->linno = plinno;
8767         pf = ckmalloc(sizeof(*pf));
8768         pf->prev = parsefile;
8769         pf->fd = -1;
8770         pf->strpush = NULL;
8771         pf->basestrpush.prev = NULL;
8772         parsefile = pf;
8773 }
8774
8775 static void
8776 popfile(void)
8777 {
8778         struct parsefile *pf = parsefile;
8779
8780         INT_OFF;
8781         if (pf->fd >= 0)
8782                 close(pf->fd);
8783         if (pf->buf)
8784                 free(pf->buf);
8785         while (pf->strpush)
8786                 popstring();
8787         parsefile = pf->prev;
8788         free(pf);
8789         parsenleft = parsefile->nleft;
8790         parselleft = parsefile->lleft;
8791         parsenextc = parsefile->nextc;
8792         plinno = parsefile->linno;
8793         INT_ON;
8794 }
8795
8796 /*
8797  * Return to top level.
8798  */
8799 static void
8800 popallfiles(void)
8801 {
8802         while (parsefile != &basepf)
8803                 popfile();
8804 }
8805
8806 /*
8807  * Close the file(s) that the shell is reading commands from.  Called
8808  * after a fork is done.
8809  */
8810 static void
8811 closescript(void)
8812 {
8813         popallfiles();
8814         if (parsefile->fd > 0) {
8815                 close(parsefile->fd);
8816                 parsefile->fd = 0;
8817         }
8818 }
8819
8820 /*
8821  * Like setinputfile, but takes an open file descriptor.  Call this with
8822  * interrupts off.
8823  */
8824 static void
8825 setinputfd(int fd, int push)
8826 {
8827         fcntl(fd, F_SETFD, FD_CLOEXEC);
8828         if (push) {
8829                 pushfile();
8830                 parsefile->buf = 0;
8831         }
8832         parsefile->fd = fd;
8833         if (parsefile->buf == NULL)
8834                 parsefile->buf = ckmalloc(IBUFSIZ);
8835         parselleft = parsenleft = 0;
8836         plinno = 1;
8837 }
8838
8839 /*
8840  * Set the input to take input from a file.  If push is set, push the
8841  * old input onto the stack first.
8842  */
8843 static int
8844 setinputfile(const char *fname, int flags)
8845 {
8846         int fd;
8847         int fd2;
8848
8849         INT_OFF;
8850         fd = open(fname, O_RDONLY);
8851         if (fd < 0) {
8852                 if (flags & INPUT_NOFILE_OK)
8853                         goto out;
8854                 ash_msg_and_raise_error("can't open %s", fname);
8855         }
8856         if (fd < 10) {
8857                 fd2 = copyfd(fd, 10);
8858                 close(fd);
8859                 if (fd2 < 0)
8860                         ash_msg_and_raise_error("out of file descriptors");
8861                 fd = fd2;
8862         }
8863         setinputfd(fd, flags & INPUT_PUSH_FILE);
8864  out:
8865         INT_ON;
8866         return fd;
8867 }
8868
8869 /*
8870  * Like setinputfile, but takes input from a string.
8871  */
8872 static void
8873 setinputstring(char *string)
8874 {
8875         INT_OFF;
8876         pushfile();
8877         parsenextc = string;
8878         parsenleft = strlen(string);
8879         parsefile->buf = NULL;
8880         plinno = 1;
8881         INT_ON;
8882 }
8883
8884
8885 /* ============ mail.c
8886  *
8887  * Routines to check for mail.
8888  */
8889
8890 #if ENABLE_ASH_MAIL
8891
8892 #define MAXMBOXES 10
8893
8894 /* times of mailboxes */
8895 static time_t mailtime[MAXMBOXES];
8896 /* Set if MAIL or MAILPATH is changed. */
8897 static int mail_var_path_changed;
8898
8899 /*
8900  * Print appropriate message(s) if mail has arrived.
8901  * If mail_var_path_changed is set,
8902  * then the value of MAIL has mail_var_path_changed,
8903  * so we just update the values.
8904  */
8905 static void
8906 chkmail(void)
8907 {
8908         const char *mpath;
8909         char *p;
8910         char *q;
8911         time_t *mtp;
8912         struct stackmark smark;
8913         struct stat statb;
8914
8915         setstackmark(&smark);
8916         mpath = mpathset() ? mpathval() : mailval();
8917         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8918                 p = padvance(&mpath, nullstr);
8919                 if (p == NULL)
8920                         break;
8921                 if (*p == '\0')
8922                         continue;
8923                 for (q = p; *q; q++);
8924 #if DEBUG
8925                 if (q[-1] != '/')
8926                         abort();
8927 #endif
8928                 q[-1] = '\0';                   /* delete trailing '/' */
8929                 if (stat(p, &statb) < 0) {
8930                         *mtp = 0;
8931                         continue;
8932                 }
8933                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8934                         fprintf(
8935                                 stderr, snlfmt,
8936                                 pathopt ? pathopt : "you have mail"
8937                         );
8938                 }
8939                 *mtp = statb.st_mtime;
8940         }
8941         mail_var_path_changed = 0;
8942         popstackmark(&smark);
8943 }
8944
8945 static void
8946 changemail(const char *val)
8947 {
8948         mail_var_path_changed++;
8949 }
8950
8951 #endif /* ASH_MAIL */
8952
8953
8954 /* ============ ??? */
8955
8956 /*
8957  * Set the shell parameters.
8958  */
8959 static void
8960 setparam(char **argv)
8961 {
8962         char **newparam;
8963         char **ap;
8964         int nparam;
8965
8966         for (nparam = 0; argv[nparam]; nparam++);
8967         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8968         while (*argv) {
8969                 *ap++ = ckstrdup(*argv++);
8970         }
8971         *ap = NULL;
8972         freeparam(&shellparam);
8973         shellparam.malloc = 1;
8974         shellparam.nparam = nparam;
8975         shellparam.p = newparam;
8976 #if ENABLE_ASH_GETOPTS
8977         shellparam.optind = 1;
8978         shellparam.optoff = -1;
8979 #endif
8980 }
8981
8982 /*
8983  * Process shell options.  The global variable argptr contains a pointer
8984  * to the argument list; we advance it past the options.
8985  */
8986 static void
8987 minus_o(char *name, int val)
8988 {
8989         int i;
8990
8991         if (name) {
8992                 for (i = 0; i < NOPTS; i++) {
8993                         if (strcmp(name, optnames(i)) == 0) {
8994                                 optlist[i] = val;
8995                                 return;
8996                         }
8997                 }
8998                 ash_msg_and_raise_error("illegal option -o %s", name);
8999         }
9000         out1str("Current option settings\n");
9001         for (i = 0; i < NOPTS; i++)
9002                 out1fmt("%-16s%s\n", optnames(i),
9003                                 optlist[i] ? "on" : "off");
9004 }
9005 static void
9006 setoption(int flag, int val)
9007 {
9008         int i;
9009
9010         for (i = 0; i < NOPTS; i++) {
9011                 if (optletters(i) == flag) {
9012                         optlist[i] = val;
9013                         return;
9014                 }
9015         }
9016         ash_msg_and_raise_error("illegal option -%c", flag);
9017         /* NOTREACHED */
9018 }
9019 static void
9020 options(int cmdline)
9021 {
9022         char *p;
9023         int val;
9024         int c;
9025
9026         if (cmdline)
9027                 minusc = NULL;
9028         while ((p = *argptr) != NULL) {
9029                 argptr++;
9030                 c = *p++;
9031                 if (c == '-') {
9032                         val = 1;
9033                         if (p[0] == '\0' || LONE_DASH(p)) {
9034                                 if (!cmdline) {
9035                                         /* "-" means turn off -x and -v */
9036                                         if (p[0] == '\0')
9037                                                 xflag = vflag = 0;
9038                                         /* "--" means reset params */
9039                                         else if (*argptr == NULL)
9040                                                 setparam(argptr);
9041                                 }
9042                                 break;    /* "-" or  "--" terminates options */
9043                         }
9044                 } else if (c == '+') {
9045                         val = 0;
9046                 } else {
9047                         argptr--;
9048                         break;
9049                 }
9050                 while ((c = *p++) != '\0') {
9051                         if (c == 'c' && cmdline) {
9052                                 minusc = p;     /* command is after shell args*/
9053                         } else if (c == 'o') {
9054                                 minus_o(*argptr, val);
9055                                 if (*argptr)
9056                                         argptr++;
9057                         } else if (cmdline && (c == '-')) {     // long options
9058                                 if (strcmp(p, "login") == 0)
9059                                         isloginsh = 1;
9060                                 break;
9061                         } else {
9062                                 setoption(c, val);
9063                         }
9064                 }
9065         }
9066 }
9067
9068 /*
9069  * The shift builtin command.
9070  */
9071 static int
9072 shiftcmd(int argc, char **argv)
9073 {
9074         int n;
9075         char **ap1, **ap2;
9076
9077         n = 1;
9078         if (argc > 1)
9079                 n = number(argv[1]);
9080         if (n > shellparam.nparam)
9081                 ash_msg_and_raise_error("can't shift that many");
9082         INT_OFF;
9083         shellparam.nparam -= n;
9084         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9085                 if (shellparam.malloc)
9086                         free(*ap1);
9087         }
9088         ap2 = shellparam.p;
9089         while ((*ap2++ = *ap1++) != NULL);
9090 #if ENABLE_ASH_GETOPTS
9091         shellparam.optind = 1;
9092         shellparam.optoff = -1;
9093 #endif
9094         INT_ON;
9095         return 0;
9096 }
9097
9098 /*
9099  * POSIX requires that 'set' (but not export or readonly) output the
9100  * variables in lexicographic order - by the locale's collating order (sigh).
9101  * Maybe we could keep them in an ordered balanced binary tree
9102  * instead of hashed lists.
9103  * For now just roll 'em through qsort for printing...
9104  */
9105 static int
9106 showvars(const char *sep_prefix, int on, int off)
9107 {
9108         const char *sep;
9109         char **ep, **epend;
9110
9111         ep = listvars(on, off, &epend);
9112         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9113
9114         sep = *sep_prefix ? " " : sep_prefix;
9115
9116         for (; ep < epend; ep++) {
9117                 const char *p;
9118                 const char *q;
9119
9120                 p = strchrnul(*ep, '=');
9121                 q = nullstr;
9122                 if (*p)
9123                         q = single_quote(++p);
9124                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9125         }
9126         return 0;
9127 }
9128
9129 /*
9130  * The set command builtin.
9131  */
9132 static int
9133 setcmd(int argc, char **argv)
9134 {
9135         if (argc == 1)
9136                 return showvars(nullstr, 0, VUNSET);
9137         INT_OFF;
9138         options(0);
9139         optschanged();
9140         if (*argptr != NULL) {
9141                 setparam(argptr);
9142         }
9143         INT_ON;
9144         return 0;
9145 }
9146
9147 #if ENABLE_ASH_RANDOM_SUPPORT
9148 /* Roughly copied from bash.. */
9149 static void
9150 change_random(const char *value)
9151 {
9152         if (value == NULL) {
9153                 /* "get", generate */
9154                 char buf[16];
9155
9156                 rseed = rseed * 1103515245 + 12345;
9157                 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9158                 /* set without recursion */
9159                 setvar(vrandom.text, buf, VNOFUNC);
9160                 vrandom.flags &= ~VNOFUNC;
9161         } else {
9162                 /* set/reset */
9163                 rseed = strtoul(value, (char **)NULL, 10);
9164         }
9165 }
9166 #endif
9167
9168 #if ENABLE_ASH_GETOPTS
9169 static int
9170 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9171 {
9172         char *p, *q;
9173         char c = '?';
9174         int done = 0;
9175         int err = 0;
9176         char s[12];
9177         char **optnext;
9178
9179         if (*param_optind < 1)
9180                 return 1;
9181         optnext = optfirst + *param_optind - 1;
9182
9183         if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9184                 p = NULL;
9185         else
9186                 p = optnext[-1] + *optoff;
9187         if (p == NULL || *p == '\0') {
9188                 /* Current word is done, advance */
9189                 p = *optnext;
9190                 if (p == NULL || *p != '-' || *++p == '\0') {
9191  atend:
9192                         p = NULL;
9193                         done = 1;
9194                         goto out;
9195                 }
9196                 optnext++;
9197                 if (LONE_DASH(p))        /* check for "--" */
9198                         goto atend;
9199         }
9200
9201         c = *p++;
9202         for (q = optstr; *q != c; ) {
9203                 if (*q == '\0') {
9204                         if (optstr[0] == ':') {
9205                                 s[0] = c;
9206                                 s[1] = '\0';
9207                                 err |= setvarsafe("OPTARG", s, 0);
9208                         } else {
9209                                 fprintf(stderr, "Illegal option -%c\n", c);
9210                                 unsetvar("OPTARG");
9211                         }
9212                         c = '?';
9213                         goto out;
9214                 }
9215                 if (*++q == ':')
9216                         q++;
9217         }
9218
9219         if (*++q == ':') {
9220                 if (*p == '\0' && (p = *optnext) == NULL) {
9221                         if (optstr[0] == ':') {
9222                                 s[0] = c;
9223                                 s[1] = '\0';
9224                                 err |= setvarsafe("OPTARG", s, 0);
9225                                 c = ':';
9226                         } else {
9227                                 fprintf(stderr, "No arg for -%c option\n", c);
9228                                 unsetvar("OPTARG");
9229                                 c = '?';
9230                         }
9231                         goto out;
9232                 }
9233
9234                 if (p == *optnext)
9235                         optnext++;
9236                 err |= setvarsafe("OPTARG", p, 0);
9237                 p = NULL;
9238         } else
9239                 err |= setvarsafe("OPTARG", nullstr, 0);
9240  out:
9241         *optoff = p ? p - *(optnext - 1) : -1;
9242         *param_optind = optnext - optfirst + 1;
9243         fmtstr(s, sizeof(s), "%d", *param_optind);
9244         err |= setvarsafe("OPTIND", s, VNOFUNC);
9245         s[0] = c;
9246         s[1] = '\0';
9247         err |= setvarsafe(optvar, s, 0);
9248         if (err) {
9249                 *param_optind = 1;
9250                 *optoff = -1;
9251                 flush_stdout_stderr();
9252                 raise_exception(EXERROR);
9253         }
9254         return done;
9255 }
9256
9257 /*
9258  * The getopts builtin.  Shellparam.optnext points to the next argument
9259  * to be processed.  Shellparam.optptr points to the next character to
9260  * be processed in the current argument.  If shellparam.optnext is NULL,
9261  * then it's the first time getopts has been called.
9262  */
9263 static int
9264 getoptscmd(int argc, char **argv)
9265 {
9266         char **optbase;
9267
9268         if (argc < 3)
9269                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9270         if (argc == 3) {
9271                 optbase = shellparam.p;
9272                 if (shellparam.optind > shellparam.nparam + 1) {
9273                         shellparam.optind = 1;
9274                         shellparam.optoff = -1;
9275                 }
9276         } else {
9277                 optbase = &argv[3];
9278                 if (shellparam.optind > argc - 2) {
9279                         shellparam.optind = 1;
9280                         shellparam.optoff = -1;
9281                 }
9282         }
9283
9284         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9285                         &shellparam.optoff);
9286 }
9287 #endif /* ASH_GETOPTS */
9288
9289
9290 /* ============ Shell parser */
9291
9292 static int tokpushback;                /* last token pushed back */
9293 #define NEOF ((union node *)&tokpushback)
9294 static int parsebackquote;             /* nonzero if we are inside backquotes */
9295 static int lasttoken;                  /* last token read */
9296 static char *wordtext;                 /* text of last word returned by readtoken */
9297 static struct nodelist *backquotelist;
9298 static union node *redirnode;
9299 static struct heredoc *heredoc;
9300 static int quoteflag;                  /* set if (part of) last token was quoted */
9301
9302 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9303 static void
9304 raise_error_syntax(const char *msg)
9305 {
9306         ash_msg_and_raise_error("syntax error: %s", msg);
9307         /* NOTREACHED */
9308 }
9309
9310 /*
9311  * Called when an unexpected token is read during the parse.  The argument
9312  * is the token that is expected, or -1 if more than one type of token can
9313  * occur at this point.
9314  */
9315 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9316 static void
9317 raise_error_unexpected_syntax(int token)
9318 {
9319         char msg[64];
9320         int l;
9321
9322         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9323         if (token >= 0)
9324                 sprintf(msg + l, " (expecting %s)", tokname(token));
9325         raise_error_syntax(msg);
9326         /* NOTREACHED */
9327 }
9328
9329 #define EOFMARKLEN 79
9330
9331 struct heredoc {
9332         struct heredoc *next;   /* next here document in list */
9333         union node *here;               /* redirection node */
9334         char *eofmark;          /* string indicating end of input */
9335         int striptabs;          /* if set, strip leading tabs */
9336 };
9337
9338 static struct heredoc *heredoclist;    /* list of here documents to read */
9339
9340 /* parsing is heavily cross-recursive, need these forward decls */
9341 static union node *andor(void);
9342 static union node *pipeline(void);
9343 static union node *parse_command(void);
9344 static void parseheredoc(void);
9345 static char peektoken(void);
9346 static int readtoken(void);
9347
9348 static union node *
9349 list(int nlflag)
9350 {
9351         union node *n1, *n2, *n3;
9352         int tok;
9353
9354         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9355         if (nlflag == 2 && peektoken())
9356                 return NULL;
9357         n1 = NULL;
9358         for (;;) {
9359                 n2 = andor();
9360                 tok = readtoken();
9361                 if (tok == TBACKGND) {
9362                         if (n2->type == NPIPE) {
9363                                 n2->npipe.backgnd = 1;
9364                         } else {
9365                                 if (n2->type != NREDIR) {
9366                                         n3 = stalloc(sizeof(struct nredir));
9367                                         n3->nredir.n = n2;
9368                                         n3->nredir.redirect = NULL;
9369                                         n2 = n3;
9370                                 }
9371                                 n2->type = NBACKGND;
9372                         }
9373                 }
9374                 if (n1 == NULL) {
9375                         n1 = n2;
9376                 } else {
9377                         n3 = stalloc(sizeof(struct nbinary));
9378                         n3->type = NSEMI;
9379                         n3->nbinary.ch1 = n1;
9380                         n3->nbinary.ch2 = n2;
9381                         n1 = n3;
9382                 }
9383                 switch (tok) {
9384                 case TBACKGND:
9385                 case TSEMI:
9386                         tok = readtoken();
9387                         /* fall through */
9388                 case TNL:
9389                         if (tok == TNL) {
9390                                 parseheredoc();
9391                                 if (nlflag == 1)
9392                                         return n1;
9393                         } else {
9394                                 tokpushback++;
9395                         }
9396                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9397                         if (peektoken())
9398                                 return n1;
9399                         break;
9400                 case TEOF:
9401                         if (heredoclist)
9402                                 parseheredoc();
9403                         else
9404                                 pungetc();              /* push back EOF on input */
9405                         return n1;
9406                 default:
9407                         if (nlflag == 1)
9408                                 raise_error_unexpected_syntax(-1);
9409                         tokpushback++;
9410                         return n1;
9411                 }
9412         }
9413 }
9414
9415 static union node *
9416 andor(void)
9417 {
9418         union node *n1, *n2, *n3;
9419         int t;
9420
9421         n1 = pipeline();
9422         for (;;) {
9423                 t = readtoken();
9424                 if (t == TAND) {
9425                         t = NAND;
9426                 } else if (t == TOR) {
9427                         t = NOR;
9428                 } else {
9429                         tokpushback++;
9430                         return n1;
9431                 }
9432                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9433                 n2 = pipeline();
9434                 n3 = stalloc(sizeof(struct nbinary));
9435                 n3->type = t;
9436                 n3->nbinary.ch1 = n1;
9437                 n3->nbinary.ch2 = n2;
9438                 n1 = n3;
9439         }
9440 }
9441
9442 static union node *
9443 pipeline(void)
9444 {
9445         union node *n1, *n2, *pipenode;
9446         struct nodelist *lp, *prev;
9447         int negate;
9448
9449         negate = 0;
9450         TRACE(("pipeline: entered\n"));
9451         if (readtoken() == TNOT) {
9452                 negate = !negate;
9453                 checkkwd = CHKKWD | CHKALIAS;
9454         } else
9455                 tokpushback++;
9456         n1 = parse_command();
9457         if (readtoken() == TPIPE) {
9458                 pipenode = stalloc(sizeof(struct npipe));
9459                 pipenode->type = NPIPE;
9460                 pipenode->npipe.backgnd = 0;
9461                 lp = stalloc(sizeof(struct nodelist));
9462                 pipenode->npipe.cmdlist = lp;
9463                 lp->n = n1;
9464                 do {
9465                         prev = lp;
9466                         lp = stalloc(sizeof(struct nodelist));
9467                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9468                         lp->n = parse_command();
9469                         prev->next = lp;
9470                 } while (readtoken() == TPIPE);
9471                 lp->next = NULL;
9472                 n1 = pipenode;
9473         }
9474         tokpushback++;
9475         if (negate) {
9476                 n2 = stalloc(sizeof(struct nnot));
9477                 n2->type = NNOT;
9478                 n2->nnot.com = n1;
9479                 return n2;
9480         }
9481         return n1;
9482 }
9483
9484 static union node *
9485 makename(void)
9486 {
9487         union node *n;
9488
9489         n = stalloc(sizeof(struct narg));
9490         n->type = NARG;
9491         n->narg.next = NULL;
9492         n->narg.text = wordtext;
9493         n->narg.backquote = backquotelist;
9494         return n;
9495 }
9496
9497 static void
9498 fixredir(union node *n, const char *text, int err)
9499 {
9500         TRACE(("Fix redir %s %d\n", text, err));
9501         if (!err)
9502                 n->ndup.vname = NULL;
9503
9504         if (isdigit(text[0]) && text[1] == '\0')
9505                 n->ndup.dupfd = text[0] - '0';
9506         else if (LONE_DASH(text))
9507                 n->ndup.dupfd = -1;
9508         else {
9509                 if (err)
9510                         raise_error_syntax("Bad fd number");
9511                 n->ndup.vname = makename();
9512         }
9513 }
9514
9515 /*
9516  * Returns true if the text contains nothing to expand (no dollar signs
9517  * or backquotes).
9518  */
9519 static int
9520 noexpand(char *text)
9521 {
9522         char *p;
9523         char c;
9524
9525         p = text;
9526         while ((c = *p++) != '\0') {
9527                 if (c == CTLQUOTEMARK)
9528                         continue;
9529                 if (c == CTLESC)
9530                         p++;
9531                 else if (SIT(c, BASESYNTAX) == CCTL)
9532                         return 0;
9533         }
9534         return 1;
9535 }
9536
9537 static void
9538 parsefname(void)
9539 {
9540         union node *n = redirnode;
9541
9542         if (readtoken() != TWORD)
9543                 raise_error_unexpected_syntax(-1);
9544         if (n->type == NHERE) {
9545                 struct heredoc *here = heredoc;
9546                 struct heredoc *p;
9547                 int i;
9548
9549                 if (quoteflag == 0)
9550                         n->type = NXHERE;
9551                 TRACE(("Here document %d\n", n->type));
9552                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9553                         raise_error_syntax("Illegal eof marker for << redirection");
9554                 rmescapes(wordtext);
9555                 here->eofmark = wordtext;
9556                 here->next = NULL;
9557                 if (heredoclist == NULL)
9558                         heredoclist = here;
9559                 else {
9560                         for (p = heredoclist; p->next; p = p->next);
9561                         p->next = here;
9562                 }
9563         } else if (n->type == NTOFD || n->type == NFROMFD) {
9564                 fixredir(n, wordtext, 0);
9565         } else {
9566                 n->nfile.fname = makename();
9567         }
9568 }
9569
9570 static union node *
9571 simplecmd(void)
9572 {
9573         union node *args, **app;
9574         union node *n = NULL;
9575         union node *vars, **vpp;
9576         union node **rpp, *redir;
9577         int savecheckkwd;
9578
9579         args = NULL;
9580         app = &args;
9581         vars = NULL;
9582         vpp = &vars;
9583         redir = NULL;
9584         rpp = &redir;
9585
9586         savecheckkwd = CHKALIAS;
9587         for (;;) {
9588                 checkkwd = savecheckkwd;
9589                 switch (readtoken()) {
9590                 case TWORD:
9591                         n = stalloc(sizeof(struct narg));
9592                         n->type = NARG;
9593                         n->narg.text = wordtext;
9594                         n->narg.backquote = backquotelist;
9595                         if (savecheckkwd && isassignment(wordtext)) {
9596                                 *vpp = n;
9597                                 vpp = &n->narg.next;
9598                         } else {
9599                                 *app = n;
9600                                 app = &n->narg.next;
9601                                 savecheckkwd = 0;
9602                         }
9603                         break;
9604                 case TREDIR:
9605                         *rpp = n = redirnode;
9606                         rpp = &n->nfile.next;
9607                         parsefname();   /* read name of redirection file */
9608                         break;
9609                 case TLP:
9610                         if (args && app == &args->narg.next
9611                          && !vars && !redir
9612                         ) {
9613                                 struct builtincmd *bcmd;
9614                                 const char *name;
9615
9616                                 /* We have a function */
9617                                 if (readtoken() != TRP)
9618                                         raise_error_unexpected_syntax(TRP);
9619                                 name = n->narg.text;
9620                                 if (!goodname(name)
9621                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9622                                 ) {
9623                                         raise_error_syntax("Bad function name");
9624                                 }
9625                                 n->type = NDEFUN;
9626                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9627                                 n->narg.next = parse_command();
9628                                 return n;
9629                         }
9630                         /* fall through */
9631                 default:
9632                         tokpushback++;
9633                         goto out;
9634                 }
9635         }
9636  out:
9637         *app = NULL;
9638         *vpp = NULL;
9639         *rpp = NULL;
9640         n = stalloc(sizeof(struct ncmd));
9641         n->type = NCMD;
9642         n->ncmd.args = args;
9643         n->ncmd.assign = vars;
9644         n->ncmd.redirect = redir;
9645         return n;
9646 }
9647
9648 static union node *
9649 parse_command(void)
9650 {
9651         union node *n1, *n2;
9652         union node *ap, **app;
9653         union node *cp, **cpp;
9654         union node *redir, **rpp;
9655         union node **rpp2;
9656         int t;
9657
9658         redir = NULL;
9659         rpp2 = &redir;
9660
9661         switch (readtoken()) {
9662         default:
9663                 raise_error_unexpected_syntax(-1);
9664                 /* NOTREACHED */
9665         case TIF:
9666                 n1 = stalloc(sizeof(struct nif));
9667                 n1->type = NIF;
9668                 n1->nif.test = list(0);
9669                 if (readtoken() != TTHEN)
9670                         raise_error_unexpected_syntax(TTHEN);
9671                 n1->nif.ifpart = list(0);
9672                 n2 = n1;
9673                 while (readtoken() == TELIF) {
9674                         n2->nif.elsepart = stalloc(sizeof(struct nif));
9675                         n2 = n2->nif.elsepart;
9676                         n2->type = NIF;
9677                         n2->nif.test = list(0);
9678                         if (readtoken() != TTHEN)
9679                                 raise_error_unexpected_syntax(TTHEN);
9680                         n2->nif.ifpart = list(0);
9681                 }
9682                 if (lasttoken == TELSE)
9683                         n2->nif.elsepart = list(0);
9684                 else {
9685                         n2->nif.elsepart = NULL;
9686                         tokpushback++;
9687                 }
9688                 t = TFI;
9689                 break;
9690         case TWHILE:
9691         case TUNTIL: {
9692                 int got;
9693                 n1 = stalloc(sizeof(struct nbinary));
9694                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9695                 n1->nbinary.ch1 = list(0);
9696                 got = readtoken();
9697                 if (got != TDO) {
9698                         TRACE(("expecting DO got %s %s\n", tokname(got),
9699                                         got == TWORD ? wordtext : ""));
9700                         raise_error_unexpected_syntax(TDO);
9701                 }
9702                 n1->nbinary.ch2 = list(0);
9703                 t = TDONE;
9704                 break;
9705         }
9706         case TFOR:
9707                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9708                         raise_error_syntax("Bad for loop variable");
9709                 n1 = stalloc(sizeof(struct nfor));
9710                 n1->type = NFOR;
9711                 n1->nfor.var = wordtext;
9712                 checkkwd = CHKKWD | CHKALIAS;
9713                 if (readtoken() == TIN) {
9714                         app = &ap;
9715                         while (readtoken() == TWORD) {
9716                                 n2 = stalloc(sizeof(struct narg));
9717                                 n2->type = NARG;
9718                                 n2->narg.text = wordtext;
9719                                 n2->narg.backquote = backquotelist;
9720                                 *app = n2;
9721                                 app = &n2->narg.next;
9722                         }
9723                         *app = NULL;
9724                         n1->nfor.args = ap;
9725                         if (lasttoken != TNL && lasttoken != TSEMI)
9726                                 raise_error_unexpected_syntax(-1);
9727                 } else {
9728                         n2 = stalloc(sizeof(struct narg));
9729                         n2->type = NARG;
9730                         n2->narg.text = (char *)dolatstr;
9731                         n2->narg.backquote = NULL;
9732                         n2->narg.next = NULL;
9733                         n1->nfor.args = n2;
9734                         /*
9735                          * Newline or semicolon here is optional (but note
9736                          * that the original Bourne shell only allowed NL).
9737                          */
9738                         if (lasttoken != TNL && lasttoken != TSEMI)
9739                                 tokpushback++;
9740                 }
9741                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9742                 if (readtoken() != TDO)
9743                         raise_error_unexpected_syntax(TDO);
9744                 n1->nfor.body = list(0);
9745                 t = TDONE;
9746                 break;
9747         case TCASE:
9748                 n1 = stalloc(sizeof(struct ncase));
9749                 n1->type = NCASE;
9750                 if (readtoken() != TWORD)
9751                         raise_error_unexpected_syntax(TWORD);
9752                 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9753                 n2->type = NARG;
9754                 n2->narg.text = wordtext;
9755                 n2->narg.backquote = backquotelist;
9756                 n2->narg.next = NULL;
9757                 do {
9758                         checkkwd = CHKKWD | CHKALIAS;
9759                 } while (readtoken() == TNL);
9760                 if (lasttoken != TIN)
9761                         raise_error_unexpected_syntax(TIN);
9762                 cpp = &n1->ncase.cases;
9763  next_case:
9764                 checkkwd = CHKNL | CHKKWD;
9765                 t = readtoken();
9766                 while (t != TESAC) {
9767                         if (lasttoken == TLP)
9768                                 readtoken();
9769                         *cpp = cp = stalloc(sizeof(struct nclist));
9770                         cp->type = NCLIST;
9771                         app = &cp->nclist.pattern;
9772                         for (;;) {
9773                                 *app = ap = stalloc(sizeof(struct narg));
9774                                 ap->type = NARG;
9775                                 ap->narg.text = wordtext;
9776                                 ap->narg.backquote = backquotelist;
9777                                 if (readtoken() != TPIPE)
9778                                         break;
9779                                 app = &ap->narg.next;
9780                                 readtoken();
9781                         }
9782                         ap->narg.next = NULL;
9783                         if (lasttoken != TRP)
9784                                 raise_error_unexpected_syntax(TRP);
9785                         cp->nclist.body = list(2);
9786
9787                         cpp = &cp->nclist.next;
9788
9789                         checkkwd = CHKNL | CHKKWD;
9790                         t = readtoken();
9791                         if (t != TESAC) {
9792                                 if (t != TENDCASE)
9793                                         raise_error_unexpected_syntax(TENDCASE);
9794                                 goto next_case;
9795                         }
9796                 }
9797                 *cpp = NULL;
9798                 goto redir;
9799         case TLP:
9800                 n1 = stalloc(sizeof(struct nredir));
9801                 n1->type = NSUBSHELL;
9802                 n1->nredir.n = list(0);
9803                 n1->nredir.redirect = NULL;
9804                 t = TRP;
9805                 break;
9806         case TBEGIN:
9807                 n1 = list(0);
9808                 t = TEND;
9809                 break;
9810         case TWORD:
9811         case TREDIR:
9812                 tokpushback++;
9813                 return simplecmd();
9814         }
9815
9816         if (readtoken() != t)
9817                 raise_error_unexpected_syntax(t);
9818
9819  redir:
9820         /* Now check for redirection which may follow command */
9821         checkkwd = CHKKWD | CHKALIAS;
9822         rpp = rpp2;
9823         while (readtoken() == TREDIR) {
9824                 *rpp = n2 = redirnode;
9825                 rpp = &n2->nfile.next;
9826                 parsefname();
9827         }
9828         tokpushback++;
9829         *rpp = NULL;
9830         if (redir) {
9831                 if (n1->type != NSUBSHELL) {
9832                         n2 = stalloc(sizeof(struct nredir));
9833                         n2->type = NREDIR;
9834                         n2->nredir.n = n1;
9835                         n1 = n2;
9836                 }
9837                 n1->nredir.redirect = redir;
9838         }
9839         return n1;
9840 }
9841
9842 /*
9843  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
9844  * is not NULL, read a here document.  In the latter case, eofmark is the
9845  * word which marks the end of the document and striptabs is true if
9846  * leading tabs should be stripped from the document.  The argument firstc
9847  * is the first character of the input token or document.
9848  *
9849  * Because C does not have internal subroutines, I have simulated them
9850  * using goto's to implement the subroutine linkage.  The following macros
9851  * will run code that appears at the end of readtoken1.
9852  */
9853
9854 static int parsebackquote;             /* nonzero if we are inside backquotes */
9855
9856 #define CHECKEND()      {goto checkend; checkend_return:;}
9857 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
9858 #define PARSESUB()      {goto parsesub; parsesub_return:;}
9859 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9860 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9861 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
9862
9863 static int
9864 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9865 {
9866         int c = firstc;
9867         char *out;
9868         int len;
9869         char line[EOFMARKLEN + 1];
9870         struct nodelist *bqlist = 0;
9871         int quotef = 0;
9872         int dblquote = 0;
9873         int varnest = 0;    /* levels of variables expansion */
9874         int arinest = 0;    /* levels of arithmetic expansion */
9875         int parenlevel = 0; /* levels of parens in arithmetic */
9876         int dqvarnest = 0;  /* levels of variables expansion within double quotes */
9877         int oldstyle = 0;
9878         int prevsyntax = 0; /* syntax before arithmetic */
9879 #if __GNUC__
9880         /* Avoid longjmp clobbering */
9881         (void) &out;
9882         (void) &quotef;
9883         (void) &dblquote;
9884         (void) &varnest;
9885         (void) &arinest;
9886         (void) &parenlevel;
9887         (void) &dqvarnest;
9888         (void) &oldstyle;
9889         (void) &prevsyntax;
9890         (void) &syntax;
9891 #endif
9892
9893         startlinno = plinno;
9894         dblquote = 0;
9895         if (syntax == DQSYNTAX)
9896                 dblquote = 1;
9897         quotef = 0;
9898         bqlist = NULL;
9899         varnest = 0;
9900         arinest = 0;
9901         parenlevel = 0;
9902         dqvarnest = 0;
9903
9904         STARTSTACKSTR(out);
9905         loop: { /* for each line, until end of word */
9906                 CHECKEND();     /* set c to PEOF if at end of here document */
9907                 for (;;) {      /* until end of line or end of word */
9908                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
9909                         switch (SIT(c, syntax)) {
9910                         case CNL:       /* '\n' */
9911                                 if (syntax == BASESYNTAX)
9912                                         goto endword;   /* exit outer loop */
9913                                 USTPUTC(c, out);
9914                                 plinno++;
9915                                 if (doprompt)
9916                                         setprompt(2);
9917                                 c = pgetc();
9918                                 goto loop;              /* continue outer loop */
9919                         case CWORD:
9920                                 USTPUTC(c, out);
9921                                 break;
9922                         case CCTL:
9923                                 if (eofmark == NULL || dblquote)
9924                                         USTPUTC(CTLESC, out);
9925                                 USTPUTC(c, out);
9926                                 break;
9927                         case CBACK:     /* backslash */
9928                                 c = pgetc2();
9929                                 if (c == PEOF) {
9930                                         USTPUTC(CTLESC, out);
9931                                         USTPUTC('\\', out);
9932                                         pungetc();
9933                                 } else if (c == '\n') {
9934                                         if (doprompt)
9935                                                 setprompt(2);
9936                                 } else {
9937                                         if (dblquote &&
9938                                                 c != '\\' && c != '`' &&
9939                                                 c != '$' && (
9940                                                         c != '"' ||
9941                                                         eofmark != NULL)
9942                                         ) {
9943                                                 USTPUTC(CTLESC, out);
9944                                                 USTPUTC('\\', out);
9945                                         }
9946                                         if (SIT(c, SQSYNTAX) == CCTL)
9947                                                 USTPUTC(CTLESC, out);
9948                                         USTPUTC(c, out);
9949                                         quotef++;
9950                                 }
9951                                 break;
9952                         case CSQUOTE:
9953                                 syntax = SQSYNTAX;
9954  quotemark:
9955                                 if (eofmark == NULL) {
9956                                         USTPUTC(CTLQUOTEMARK, out);
9957                                 }
9958                                 break;
9959                         case CDQUOTE:
9960                                 syntax = DQSYNTAX;
9961                                 dblquote = 1;
9962                                 goto quotemark;
9963                         case CENDQUOTE:
9964                                 if (eofmark != NULL && arinest == 0
9965                                  && varnest == 0
9966                                 ) {
9967                                         USTPUTC(c, out);
9968                                 } else {
9969                                         if (dqvarnest == 0) {
9970                                                 syntax = BASESYNTAX;
9971                                                 dblquote = 0;
9972                                         }
9973                                         quotef++;
9974                                         goto quotemark;
9975                                 }
9976                                 break;
9977                         case CVAR:      /* '$' */
9978                                 PARSESUB();             /* parse substitution */
9979                                 break;
9980                         case CENDVAR:   /* '}' */
9981                                 if (varnest > 0) {
9982                                         varnest--;
9983                                         if (dqvarnest > 0) {
9984                                                 dqvarnest--;
9985                                         }
9986                                         USTPUTC(CTLENDVAR, out);
9987                                 } else {
9988                                         USTPUTC(c, out);
9989                                 }
9990                                 break;
9991 #if ENABLE_ASH_MATH_SUPPORT
9992                         case CLP:       /* '(' in arithmetic */
9993                                 parenlevel++;
9994                                 USTPUTC(c, out);
9995                                 break;
9996                         case CRP:       /* ')' in arithmetic */
9997                                 if (parenlevel > 0) {
9998                                         USTPUTC(c, out);
9999                                         --parenlevel;
10000                                 } else {
10001                                         if (pgetc() == ')') {
10002                                                 if (--arinest == 0) {
10003                                                         USTPUTC(CTLENDARI, out);
10004                                                         syntax = prevsyntax;
10005                                                         if (syntax == DQSYNTAX)
10006                                                                 dblquote = 1;
10007                                                         else
10008                                                                 dblquote = 0;
10009                                                 } else
10010                                                         USTPUTC(')', out);
10011                                         } else {
10012                                                 /*
10013                                                  * unbalanced parens
10014                                                  *  (don't 2nd guess - no error)
10015                                                  */
10016                                                 pungetc();
10017                                                 USTPUTC(')', out);
10018                                         }
10019                                 }
10020                                 break;
10021 #endif
10022                         case CBQUOTE:   /* '`' */
10023                                 PARSEBACKQOLD();
10024                                 break;
10025                         case CENDFILE:
10026                                 goto endword;           /* exit outer loop */
10027                         case CIGN:
10028                                 break;
10029                         default:
10030                                 if (varnest == 0)
10031                                         goto endword;   /* exit outer loop */
10032 #if ENABLE_ASH_ALIAS
10033                                 if (c != PEOA)
10034 #endif
10035                                         USTPUTC(c, out);
10036
10037                         }
10038                         c = pgetc_macro();
10039                 }
10040         }
10041  endword:
10042 #if ENABLE_ASH_MATH_SUPPORT
10043         if (syntax == ARISYNTAX)
10044                 raise_error_syntax("Missing '))'");
10045 #endif
10046         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10047                 raise_error_syntax("Unterminated quoted string");
10048         if (varnest != 0) {
10049                 startlinno = plinno;
10050                 /* { */
10051                 raise_error_syntax("Missing '}'");
10052         }
10053         USTPUTC('\0', out);
10054         len = out - (char *)stackblock();
10055         out = stackblock();
10056         if (eofmark == NULL) {
10057                 if ((c == '>' || c == '<')
10058                  && quotef == 0
10059                  && len <= 2
10060                  && (*out == '\0' || isdigit(*out))) {
10061                         PARSEREDIR();
10062                         return lasttoken = TREDIR;
10063                 } else {
10064                         pungetc();
10065                 }
10066         }
10067         quoteflag = quotef;
10068         backquotelist = bqlist;
10069         grabstackblock(len);
10070         wordtext = out;
10071         lasttoken = TWORD;
10072         return lasttoken;
10073 /* end of readtoken routine */
10074
10075 /*
10076  * Check to see whether we are at the end of the here document.  When this
10077  * is called, c is set to the first character of the next input line.  If
10078  * we are at the end of the here document, this routine sets the c to PEOF.
10079  */
10080 checkend: {
10081         if (eofmark) {
10082 #if ENABLE_ASH_ALIAS
10083                 if (c == PEOA) {
10084                         c = pgetc2();
10085                 }
10086 #endif
10087                 if (striptabs) {
10088                         while (c == '\t') {
10089                                 c = pgetc2();
10090                         }
10091                 }
10092                 if (c == *eofmark) {
10093                         if (pfgets(line, sizeof(line)) != NULL) {
10094                                 char *p, *q;
10095
10096                                 p = line;
10097                                 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10098                                 if (*p == '\n' && *q == '\0') {
10099                                         c = PEOF;
10100                                         plinno++;
10101                                         needprompt = doprompt;
10102                                 } else {
10103                                         pushstring(line, NULL);
10104                                 }
10105                         }
10106                 }
10107         }
10108         goto checkend_return;
10109 }
10110
10111 /*
10112  * Parse a redirection operator.  The variable "out" points to a string
10113  * specifying the fd to be redirected.  The variable "c" contains the
10114  * first character of the redirection operator.
10115  */
10116 parseredir: {
10117         char fd = *out;
10118         union node *np;
10119
10120         np = stalloc(sizeof(struct nfile));
10121         if (c == '>') {
10122                 np->nfile.fd = 1;
10123                 c = pgetc();
10124                 if (c == '>')
10125                         np->type = NAPPEND;
10126                 else if (c == '|')
10127                         np->type = NCLOBBER;
10128                 else if (c == '&')
10129                         np->type = NTOFD;
10130                 else {
10131                         np->type = NTO;
10132                         pungetc();
10133                 }
10134         } else {        /* c == '<' */
10135                 np->nfile.fd = 0;
10136                 c = pgetc();
10137                 switch (c) {
10138                 case '<':
10139                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10140                                 np = stalloc(sizeof(struct nhere));
10141                                 np->nfile.fd = 0;
10142                         }
10143                         np->type = NHERE;
10144                         heredoc = stalloc(sizeof(struct heredoc));
10145                         heredoc->here = np;
10146                         c = pgetc();
10147                         if (c == '-') {
10148                                 heredoc->striptabs = 1;
10149                         } else {
10150                                 heredoc->striptabs = 0;
10151                                 pungetc();
10152                         }
10153                         break;
10154
10155                 case '&':
10156                         np->type = NFROMFD;
10157                         break;
10158
10159                 case '>':
10160                         np->type = NFROMTO;
10161                         break;
10162
10163                 default:
10164                         np->type = NFROM;
10165                         pungetc();
10166                         break;
10167                 }
10168         }
10169         if (fd != '\0')
10170                 np->nfile.fd = fd - '0';
10171         redirnode = np;
10172         goto parseredir_return;
10173 }
10174
10175 /*
10176  * Parse a substitution.  At this point, we have read the dollar sign
10177  * and nothing else.
10178  */
10179
10180 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10181  * (assuming ascii char codes, as the original implementation did) */
10182 #define is_special(c) \
10183         ((((unsigned int)c) - 33 < 32) \
10184                         && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10185 parsesub: {
10186         int subtype;
10187         int typeloc;
10188         int flags;
10189         char *p;
10190         static const char types[] = "}-+?=";
10191
10192         c = pgetc();
10193         if (
10194                 c <= PEOA_OR_PEOF  ||
10195                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10196         ) {
10197                 USTPUTC('$', out);
10198                 pungetc();
10199         } else if (c == '(') {  /* $(command) or $((arith)) */
10200                 if (pgetc() == '(') {
10201 #if ENABLE_ASH_MATH_SUPPORT
10202                         PARSEARITH();
10203 #else
10204                         raise_error_syntax("We unsupport $((arith))");
10205 #endif
10206                 } else {
10207                         pungetc();
10208                         PARSEBACKQNEW();
10209                 }
10210         } else {
10211                 USTPUTC(CTLVAR, out);
10212                 typeloc = out - (char *)stackblock();
10213                 USTPUTC(VSNORMAL, out);
10214                 subtype = VSNORMAL;
10215                 if (c == '{') {
10216                         c = pgetc();
10217                         if (c == '#') {
10218                                 c = pgetc();
10219                                 if (c == '}')
10220                                         c = '#';
10221                                 else
10222                                         subtype = VSLENGTH;
10223                         } else
10224                                 subtype = 0;
10225                 }
10226                 if (c > PEOA_OR_PEOF && is_name(c)) {
10227                         do {
10228                                 STPUTC(c, out);
10229                                 c = pgetc();
10230                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10231                 } else if (isdigit(c)) {
10232                         do {
10233                                 STPUTC(c, out);
10234                                 c = pgetc();
10235                         } while (isdigit(c));
10236                 } else if (is_special(c)) {
10237                         USTPUTC(c, out);
10238                         c = pgetc();
10239                 } else
10240  badsub:                raise_error_syntax("Bad substitution");
10241
10242                 STPUTC('=', out);
10243                 flags = 0;
10244                 if (subtype == 0) {
10245                         switch (c) {
10246                         case ':':
10247                                 flags = VSNUL;
10248                                 c = pgetc();
10249                                 /*FALLTHROUGH*/
10250                         default:
10251                                 p = strchr(types, c);
10252                                 if (p == NULL)
10253                                         goto badsub;
10254                                 subtype = p - types + VSNORMAL;
10255                                 break;
10256                         case '%':
10257                         case '#':
10258                                 {
10259                                         int cc = c;
10260                                         subtype = c == '#' ? VSTRIMLEFT :
10261                                                              VSTRIMRIGHT;
10262                                         c = pgetc();
10263                                         if (c == cc)
10264                                                 subtype++;
10265                                         else
10266                                                 pungetc();
10267                                         break;
10268                                 }
10269                         }
10270                 } else {
10271                         pungetc();
10272                 }
10273                 if (dblquote || arinest)
10274                         flags |= VSQUOTE;
10275                 *((char *)stackblock() + typeloc) = subtype | flags;
10276                 if (subtype != VSNORMAL) {
10277                         varnest++;
10278                         if (dblquote || arinest) {
10279                                 dqvarnest++;
10280                         }
10281                 }
10282         }
10283         goto parsesub_return;
10284 }
10285
10286 /*
10287  * Called to parse command substitutions.  Newstyle is set if the command
10288  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10289  * list of commands (passed by reference), and savelen is the number of
10290  * characters on the top of the stack which must be preserved.
10291  */
10292 parsebackq: {
10293         struct nodelist **nlpp;
10294         int savepbq;
10295         union node *n;
10296         char *volatile str;
10297         struct jmploc jmploc;
10298         struct jmploc *volatile savehandler;
10299         size_t savelen;
10300         int saveprompt = 0;
10301 #ifdef __GNUC__
10302         (void) &saveprompt;
10303 #endif
10304
10305         savepbq = parsebackquote;
10306         if (setjmp(jmploc.loc)) {
10307                 if (str)
10308                         free(str);
10309                 parsebackquote = 0;
10310                 exception_handler = savehandler;
10311                 longjmp(exception_handler->loc, 1);
10312         }
10313         INT_OFF;
10314         str = NULL;
10315         savelen = out - (char *)stackblock();
10316         if (savelen > 0) {
10317                 str = ckmalloc(savelen);
10318                 memcpy(str, stackblock(), savelen);
10319         }
10320         savehandler = exception_handler;
10321         exception_handler = &jmploc;
10322         INT_ON;
10323         if (oldstyle) {
10324                 /* We must read until the closing backquote, giving special
10325                    treatment to some slashes, and then push the string and
10326                    reread it as input, interpreting it normally.  */
10327                 char *pout;
10328                 int pc;
10329                 size_t psavelen;
10330                 char *pstr;
10331
10332
10333                 STARTSTACKSTR(pout);
10334                 for (;;) {
10335                         if (needprompt) {
10336                                 setprompt(2);
10337                         }
10338                         pc = pgetc();
10339                         switch (pc) {
10340                         case '`':
10341                                 goto done;
10342
10343                         case '\\':
10344                                 pc = pgetc();
10345                                 if (pc == '\n') {
10346                                         plinno++;
10347                                         if (doprompt)
10348                                                 setprompt(2);
10349                                         /*
10350                                          * If eating a newline, avoid putting
10351                                          * the newline into the new character
10352                                          * stream (via the STPUTC after the
10353                                          * switch).
10354                                          */
10355                                         continue;
10356                                 }
10357                                 if (pc != '\\' && pc != '`' && pc != '$'
10358                                  && (!dblquote || pc != '"'))
10359                                         STPUTC('\\', pout);
10360                                 if (pc > PEOA_OR_PEOF) {
10361                                         break;
10362                                 }
10363                                 /* fall through */
10364
10365                         case PEOF:
10366 #if ENABLE_ASH_ALIAS
10367                         case PEOA:
10368 #endif
10369                                 startlinno = plinno;
10370                                 raise_error_syntax("EOF in backquote substitution");
10371
10372                         case '\n':
10373                                 plinno++;
10374                                 needprompt = doprompt;
10375                                 break;
10376
10377                         default:
10378                                 break;
10379                         }
10380                         STPUTC(pc, pout);
10381                 }
10382  done:
10383                 STPUTC('\0', pout);
10384                 psavelen = pout - (char *)stackblock();
10385                 if (psavelen > 0) {
10386                         pstr = grabstackstr(pout);
10387                         setinputstring(pstr);
10388                 }
10389         }
10390         nlpp = &bqlist;
10391         while (*nlpp)
10392                 nlpp = &(*nlpp)->next;
10393         *nlpp = stalloc(sizeof(**nlpp));
10394         (*nlpp)->next = NULL;
10395         parsebackquote = oldstyle;
10396
10397         if (oldstyle) {
10398                 saveprompt = doprompt;
10399                 doprompt = 0;
10400         }
10401
10402         n = list(2);
10403
10404         if (oldstyle)
10405                 doprompt = saveprompt;
10406         else if (readtoken() != TRP)
10407                 raise_error_unexpected_syntax(TRP);
10408
10409         (*nlpp)->n = n;
10410         if (oldstyle) {
10411                 /*
10412                  * Start reading from old file again, ignoring any pushed back
10413                  * tokens left from the backquote parsing
10414                  */
10415                 popfile();
10416                 tokpushback = 0;
10417         }
10418         while (stackblocksize() <= savelen)
10419                 growstackblock();
10420         STARTSTACKSTR(out);
10421         if (str) {
10422                 memcpy(out, str, savelen);
10423                 STADJUST(savelen, out);
10424                 INT_OFF;
10425                 free(str);
10426                 str = NULL;
10427                 INT_ON;
10428         }
10429         parsebackquote = savepbq;
10430         exception_handler = savehandler;
10431         if (arinest || dblquote)
10432                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10433         else
10434                 USTPUTC(CTLBACKQ, out);
10435         if (oldstyle)
10436                 goto parsebackq_oldreturn;
10437         goto parsebackq_newreturn;
10438 }
10439
10440 #if ENABLE_ASH_MATH_SUPPORT
10441 /*
10442  * Parse an arithmetic expansion (indicate start of one and set state)
10443  */
10444 parsearith: {
10445         if (++arinest == 1) {
10446                 prevsyntax = syntax;
10447                 syntax = ARISYNTAX;
10448                 USTPUTC(CTLARI, out);
10449                 if (dblquote)
10450                         USTPUTC('"', out);
10451                 else
10452                         USTPUTC(' ', out);
10453         } else {
10454                 /*
10455                  * we collapse embedded arithmetic expansion to
10456                  * parenthesis, which should be equivalent
10457                  */
10458                 USTPUTC('(', out);
10459         }
10460         goto parsearith_return;
10461 }
10462 #endif
10463
10464 } /* end of readtoken */
10465
10466 /*
10467  * Read the next input token.
10468  * If the token is a word, we set backquotelist to the list of cmds in
10469  *      backquotes.  We set quoteflag to true if any part of the word was
10470  *      quoted.
10471  * If the token is TREDIR, then we set redirnode to a structure containing
10472  *      the redirection.
10473  * In all cases, the variable startlinno is set to the number of the line
10474  *      on which the token starts.
10475  *
10476  * [Change comment:  here documents and internal procedures]
10477  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10478  *  word parsing code into a separate routine.  In this case, readtoken
10479  *  doesn't need to have any internal procedures, but parseword does.
10480  *  We could also make parseoperator in essence the main routine, and
10481  *  have parseword (readtoken1?) handle both words and redirection.]
10482  */
10483 #define NEW_xxreadtoken
10484 #ifdef NEW_xxreadtoken
10485 /* singles must be first! */
10486 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10487
10488 static const char xxreadtoken_tokens[] = {
10489         TNL, TLP, TRP,          /* only single occurrence allowed */
10490         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10491         TEOF,                   /* corresponds to trailing nul */
10492         TAND, TOR, TENDCASE,    /* if double occurrence */
10493 };
10494
10495 #define xxreadtoken_doubles \
10496         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10497 #define xxreadtoken_singles \
10498         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10499
10500 static int
10501 xxreadtoken(void)
10502 {
10503         int c;
10504
10505         if (tokpushback) {
10506                 tokpushback = 0;
10507                 return lasttoken;
10508         }
10509         if (needprompt) {
10510                 setprompt(2);
10511         }
10512         startlinno = plinno;
10513         for (;;) {                      /* until token or start of word found */
10514                 c = pgetc_macro();
10515
10516                 if ((c != ' ') && (c != '\t')
10517 #if ENABLE_ASH_ALIAS
10518                  && (c != PEOA)
10519 #endif
10520                 ) {
10521                         if (c == '#') {
10522                                 while ((c = pgetc()) != '\n' && c != PEOF);
10523                                 pungetc();
10524                         } else if (c == '\\') {
10525                                 if (pgetc() != '\n') {
10526                                         pungetc();
10527                                         goto READTOKEN1;
10528                                 }
10529                                 startlinno = ++plinno;
10530                                 if (doprompt)
10531                                         setprompt(2);
10532                         } else {
10533                                 const char *p
10534                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10535
10536                                 if (c != PEOF) {
10537                                         if (c == '\n') {
10538                                                 plinno++;
10539                                                 needprompt = doprompt;
10540                                         }
10541
10542                                         p = strchr(xxreadtoken_chars, c);
10543                                         if (p == NULL) {
10544  READTOKEN1:
10545                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10546                                         }
10547
10548                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10549                                                 if (pgetc() == *p) {    /* double occurrence? */
10550                                                         p += xxreadtoken_doubles + 1;
10551                                                 } else {
10552                                                         pungetc();
10553                                                 }
10554                                         }
10555                                 }
10556                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10557                         }
10558                 }
10559         } /* for */
10560 }
10561 #else
10562 #define RETURN(token)   return lasttoken = token
10563 static int
10564 xxreadtoken(void)
10565 {
10566         int c;
10567
10568         if (tokpushback) {
10569                 tokpushback = 0;
10570                 return lasttoken;
10571         }
10572         if (needprompt) {
10573                 setprompt(2);
10574         }
10575         startlinno = plinno;
10576         for (;;) {      /* until token or start of word found */
10577                 c = pgetc_macro();
10578                 switch (c) {
10579                 case ' ': case '\t':
10580 #if ENABLE_ASH_ALIAS
10581                 case PEOA:
10582 #endif
10583                         continue;
10584                 case '#':
10585                         while ((c = pgetc()) != '\n' && c != PEOF);
10586                         pungetc();
10587                         continue;
10588                 case '\\':
10589                         if (pgetc() == '\n') {
10590                                 startlinno = ++plinno;
10591                                 if (doprompt)
10592                                         setprompt(2);
10593                                 continue;
10594                         }
10595                         pungetc();
10596                         goto breakloop;
10597                 case '\n':
10598                         plinno++;
10599                         needprompt = doprompt;
10600                         RETURN(TNL);
10601                 case PEOF:
10602                         RETURN(TEOF);
10603                 case '&':
10604                         if (pgetc() == '&')
10605                                 RETURN(TAND);
10606                         pungetc();
10607                         RETURN(TBACKGND);
10608                 case '|':
10609                         if (pgetc() == '|')
10610                                 RETURN(TOR);
10611                         pungetc();
10612                         RETURN(TPIPE);
10613                 case ';':
10614                         if (pgetc() == ';')
10615                                 RETURN(TENDCASE);
10616                         pungetc();
10617                         RETURN(TSEMI);
10618                 case '(':
10619                         RETURN(TLP);
10620                 case ')':
10621                         RETURN(TRP);
10622                 default:
10623                         goto breakloop;
10624                 }
10625         }
10626  breakloop:
10627         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10628 #undef RETURN
10629 }
10630 #endif /* NEW_xxreadtoken */
10631
10632 static int
10633 readtoken(void)
10634 {
10635         int t;
10636 #if DEBUG
10637         int alreadyseen = tokpushback;
10638 #endif
10639
10640 #if ENABLE_ASH_ALIAS
10641  top:
10642 #endif
10643
10644         t = xxreadtoken();
10645
10646         /*
10647          * eat newlines
10648          */
10649         if (checkkwd & CHKNL) {
10650                 while (t == TNL) {
10651                         parseheredoc();
10652                         t = xxreadtoken();
10653                 }
10654         }
10655
10656         if (t != TWORD || quoteflag) {
10657                 goto out;
10658         }
10659
10660         /*
10661          * check for keywords
10662          */
10663         if (checkkwd & CHKKWD) {
10664                 const char *const *pp;
10665
10666                 pp = findkwd(wordtext);
10667                 if (pp) {
10668                         lasttoken = t = pp - tokname_array;
10669                         TRACE(("keyword %s recognized\n", tokname(t)));
10670                         goto out;
10671                 }
10672         }
10673
10674         if (checkkwd & CHKALIAS) {
10675 #if ENABLE_ASH_ALIAS
10676                 struct alias *ap;
10677                 ap = lookupalias(wordtext, 1);
10678                 if (ap != NULL) {
10679                         if (*ap->val) {
10680                                 pushstring(ap->val, ap);
10681                         }
10682                         goto top;
10683                 }
10684 #endif
10685         }
10686  out:
10687         checkkwd = 0;
10688 #if DEBUG
10689         if (!alreadyseen)
10690                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10691         else
10692                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10693 #endif
10694         return t;
10695 }
10696
10697 static char
10698 peektoken(void)
10699 {
10700         int t;
10701
10702         t = readtoken();
10703         tokpushback++;
10704         return tokname_array[t][0];
10705 }
10706
10707 /*
10708  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
10709  * valid parse tree indicating a blank line.)
10710  */
10711 static union node *
10712 parsecmd(int interact)
10713 {
10714         int t;
10715
10716         tokpushback = 0;
10717         doprompt = interact;
10718         if (doprompt)
10719                 setprompt(doprompt);
10720         needprompt = 0;
10721         t = readtoken();
10722         if (t == TEOF)
10723                 return NEOF;
10724         if (t == TNL)
10725                 return NULL;
10726         tokpushback++;
10727         return list(1);
10728 }
10729
10730 /*
10731  * Input any here documents.
10732  */
10733 static void
10734 parseheredoc(void)
10735 {
10736         struct heredoc *here;
10737         union node *n;
10738
10739         here = heredoclist;
10740         heredoclist = 0;
10741
10742         while (here) {
10743                 if (needprompt) {
10744                         setprompt(2);
10745                 }
10746                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10747                                 here->eofmark, here->striptabs);
10748                 n = stalloc(sizeof(struct narg));
10749                 n->narg.type = NARG;
10750                 n->narg.next = NULL;
10751                 n->narg.text = wordtext;
10752                 n->narg.backquote = backquotelist;
10753                 here->here->nhere.doc = n;
10754                 here = here->next;
10755         }
10756 }
10757
10758
10759 /*
10760  * called by editline -- any expansions to the prompt should be added here.
10761  */
10762 #if ENABLE_ASH_EXPAND_PRMT
10763 static const char *
10764 expandstr(const char *ps)
10765 {
10766         union node n;
10767
10768         /* XXX Fix (char *) cast. */
10769         setinputstring((char *)ps);
10770         readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10771         popfile();
10772
10773         n.narg.type = NARG;
10774         n.narg.next = NULL;
10775         n.narg.text = wordtext;
10776         n.narg.backquote = backquotelist;
10777
10778         expandarg(&n, NULL, 0);
10779         return stackblock();
10780 }
10781 #endif
10782
10783 /*
10784  * Execute a command or commands contained in a string.
10785  */
10786 static int
10787 evalstring(char *s, int mask)
10788 {
10789         union node *n;
10790         struct stackmark smark;
10791         int skip;
10792
10793         setinputstring(s);
10794         setstackmark(&smark);
10795
10796         skip = 0;
10797         while ((n = parsecmd(0)) != NEOF) {
10798                 evaltree(n, 0);
10799                 popstackmark(&smark);
10800                 skip = evalskip;
10801                 if (skip)
10802                         break;
10803         }
10804         popfile();
10805
10806         skip &= mask;
10807         evalskip = skip;
10808         return skip;
10809 }
10810
10811 /*
10812  * The eval command.
10813  */
10814 static int
10815 evalcmd(int argc, char **argv)
10816 {
10817         char *p;
10818         char *concat;
10819         char **ap;
10820
10821         if (argc > 1) {
10822                 p = argv[1];
10823                 if (argc > 2) {
10824                         STARTSTACKSTR(concat);
10825                         ap = argv + 2;
10826                         for (;;) {
10827                                 concat = stack_putstr(p, concat);
10828                                 p = *ap++;
10829                                 if (p == NULL)
10830                                         break;
10831                                 STPUTC(' ', concat);
10832                         }
10833                         STPUTC('\0', concat);
10834                         p = grabstackstr(concat);
10835                 }
10836                 evalstring(p, ~SKIPEVAL);
10837
10838         }
10839         return exitstatus;
10840 }
10841
10842 /*
10843  * Read and execute commands.  "Top" is nonzero for the top level command
10844  * loop; it turns on prompting if the shell is interactive.
10845  */
10846 static int
10847 cmdloop(int top)
10848 {
10849         union node *n;
10850         struct stackmark smark;
10851         int inter;
10852         int numeof = 0;
10853
10854         TRACE(("cmdloop(%d) called\n", top));
10855         for (;;) {
10856                 int skip;
10857
10858                 setstackmark(&smark);
10859 #if JOBS
10860                 if (jobctl)
10861                         showjobs(stderr, SHOW_CHANGED);
10862 #endif
10863                 inter = 0;
10864                 if (iflag && top) {
10865                         inter++;
10866 #if ENABLE_ASH_MAIL
10867                         chkmail();
10868 #endif
10869                 }
10870                 n = parsecmd(inter);
10871                 /* showtree(n); DEBUG */
10872                 if (n == NEOF) {
10873                         if (!top || numeof >= 50)
10874                                 break;
10875                         if (!stoppedjobs()) {
10876                                 if (!Iflag)
10877                                         break;
10878                                 out2str("\nUse \"exit\" to leave shell.\n");
10879                         }
10880                         numeof++;
10881                 } else if (nflag == 0) {
10882                         job_warning = (job_warning == 2) ? 1 : 0;
10883                         numeof = 0;
10884                         evaltree(n, 0);
10885                 }
10886                 popstackmark(&smark);
10887                 skip = evalskip;
10888
10889                 if (skip) {
10890                         evalskip = 0;
10891                         return skip & SKIPEVAL;
10892                 }
10893         }
10894         return 0;
10895 }
10896
10897 /*
10898  * Take commands from a file.  To be compatible we should do a path
10899  * search for the file, which is necessary to find sub-commands.
10900  */
10901 static char *
10902 find_dot_file(char *name)
10903 {
10904         char *fullname;
10905         const char *path = pathval();
10906         struct stat statb;
10907
10908         /* don't try this for absolute or relative paths */
10909         if (strchr(name, '/'))
10910                 return name;
10911
10912         while ((fullname = padvance(&path, name)) != NULL) {
10913                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
10914                         /*
10915                          * Don't bother freeing here, since it will
10916                          * be freed by the caller.
10917                          */
10918                         return fullname;
10919                 }
10920                 stunalloc(fullname);
10921         }
10922
10923         /* not found in the PATH */
10924         ash_msg_and_raise_error("%s: not found", name);
10925         /* NOTREACHED */
10926 }
10927
10928 static int
10929 dotcmd(int argc, char **argv)
10930 {
10931         struct strlist *sp;
10932         volatile struct shparam saveparam;
10933         int status = 0;
10934
10935         for (sp = cmdenviron; sp; sp = sp->next)
10936                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10937
10938         if (argc >= 2) {        /* That's what SVR2 does */
10939                 char *fullname;
10940
10941                 fullname = find_dot_file(argv[1]);
10942
10943                 if (argc > 2) {
10944                         saveparam = shellparam;
10945                         shellparam.malloc = 0;
10946                         shellparam.nparam = argc - 2;
10947                         shellparam.p = argv + 2;
10948                 };
10949
10950                 setinputfile(fullname, INPUT_PUSH_FILE);
10951                 commandname = fullname;
10952                 cmdloop(0);
10953                 popfile();
10954
10955                 if (argc > 2) {
10956                         freeparam(&shellparam);
10957                         shellparam = saveparam;
10958                 };
10959                 status = exitstatus;
10960         }
10961         return status;
10962 }
10963
10964 static int
10965 exitcmd(int argc, char **argv)
10966 {
10967         if (stoppedjobs())
10968                 return 0;
10969         if (argc > 1)
10970                 exitstatus = number(argv[1]);
10971         raise_exception(EXEXIT);
10972         /* NOTREACHED */
10973 }
10974
10975 #if ENABLE_ASH_BUILTIN_ECHO
10976 static int
10977 echocmd(int argc, char **argv)
10978 {
10979         return bb_echo(argv);
10980 }
10981 #endif
10982
10983 #if ENABLE_ASH_BUILTIN_TEST
10984 static int
10985 testcmd(int argc, char **argv)
10986 {
10987         return test_main(argc, argv);
10988 }
10989 #endif
10990
10991 /*
10992  * Read a file containing shell functions.
10993  */
10994 static void
10995 readcmdfile(char *name)
10996 {
10997         setinputfile(name, INPUT_PUSH_FILE);
10998         cmdloop(0);
10999         popfile();
11000 }
11001
11002
11003 /* ============ find_command inplementation */
11004
11005 /*
11006  * Resolve a command name.  If you change this routine, you may have to
11007  * change the shellexec routine as well.
11008  */
11009 static void
11010 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11011 {
11012         struct tblentry *cmdp;
11013         int idx;
11014         int prev;
11015         char *fullname;
11016         struct stat statb;
11017         int e;
11018         int updatetbl;
11019         struct builtincmd *bcmd;
11020
11021         /* If name contains a slash, don't use PATH or hash table */
11022         if (strchr(name, '/') != NULL) {
11023                 entry->u.index = -1;
11024                 if (act & DO_ABS) {
11025                         while (stat(name, &statb) < 0) {
11026 #ifdef SYSV
11027                                 if (errno == EINTR)
11028                                         continue;
11029 #endif
11030                                 entry->cmdtype = CMDUNKNOWN;
11031                                 return;
11032                         }
11033                 }
11034                 entry->cmdtype = CMDNORMAL;
11035                 return;
11036         }
11037
11038 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11039
11040         updatetbl = (path == pathval());
11041         if (!updatetbl) {
11042                 act |= DO_ALTPATH;
11043                 if (strstr(path, "%builtin") != NULL)
11044                         act |= DO_ALTBLTIN;
11045         }
11046
11047         /* If name is in the table, check answer will be ok */
11048         cmdp = cmdlookup(name, 0);
11049         if (cmdp != NULL) {
11050                 int bit;
11051
11052                 switch (cmdp->cmdtype) {
11053                 default:
11054 #if DEBUG
11055                         abort();
11056 #endif
11057                 case CMDNORMAL:
11058                         bit = DO_ALTPATH;
11059                         break;
11060                 case CMDFUNCTION:
11061                         bit = DO_NOFUNC;
11062                         break;
11063                 case CMDBUILTIN:
11064                         bit = DO_ALTBLTIN;
11065                         break;
11066                 }
11067                 if (act & bit) {
11068                         updatetbl = 0;
11069                         cmdp = NULL;
11070                 } else if (cmdp->rehash == 0)
11071                         /* if not invalidated by cd, we're done */
11072                         goto success;
11073         }
11074
11075         /* If %builtin not in path, check for builtin next */
11076         bcmd = find_builtin(name);
11077         if (bcmd) {
11078                 if (IS_BUILTIN_REGULAR(bcmd))
11079                         goto builtin_success;
11080                 if (act & DO_ALTPATH) {
11081                         if (!(act & DO_ALTBLTIN))
11082                                 goto builtin_success;
11083                 } else if (builtinloc <= 0) {
11084                         goto builtin_success;
11085                 }
11086         }
11087
11088 #if ENABLE_FEATURE_SH_STANDALONE
11089         if (find_applet_by_name(name)) {
11090                 entry->cmdtype = CMDNORMAL;
11091                 entry->u.index = -1;
11092                 return;
11093         }
11094 #endif
11095
11096         /* We have to search path. */
11097         prev = -1;              /* where to start */
11098         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11099                 if (cmdp->cmdtype == CMDBUILTIN)
11100                         prev = builtinloc;
11101                 else
11102                         prev = cmdp->param.index;
11103         }
11104
11105         e = ENOENT;
11106         idx = -1;
11107  loop:
11108         while ((fullname = padvance(&path, name)) != NULL) {
11109                 stunalloc(fullname);
11110                 idx++;
11111                 if (pathopt) {
11112                         if (prefix(pathopt, "builtin")) {
11113                                 if (bcmd)
11114                                         goto builtin_success;
11115                                 continue;
11116                         } else if (!(act & DO_NOFUNC) &&
11117                                    prefix(pathopt, "func")) {
11118                                 /* handled below */
11119                         } else {
11120                                 /* ignore unimplemented options */
11121                                 continue;
11122                         }
11123                 }
11124                 /* if rehash, don't redo absolute path names */
11125                 if (fullname[0] == '/' && idx <= prev) {
11126                         if (idx < prev)
11127                                 continue;
11128                         TRACE(("searchexec \"%s\": no change\n", name));
11129                         goto success;
11130                 }
11131                 while (stat(fullname, &statb) < 0) {
11132 #ifdef SYSV
11133                         if (errno == EINTR)
11134                                 continue;
11135 #endif
11136                         if (errno != ENOENT && errno != ENOTDIR)
11137                                 e = errno;
11138                         goto loop;
11139                 }
11140                 e = EACCES;     /* if we fail, this will be the error */
11141                 if (!S_ISREG(statb.st_mode))
11142                         continue;
11143                 if (pathopt) {          /* this is a %func directory */
11144                         stalloc(strlen(fullname) + 1);
11145                         readcmdfile(fullname);
11146                         cmdp = cmdlookup(name, 0);
11147                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11148                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11149                         stunalloc(fullname);
11150                         goto success;
11151                 }
11152                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11153                 if (!updatetbl) {
11154                         entry->cmdtype = CMDNORMAL;
11155                         entry->u.index = idx;
11156                         return;
11157                 }
11158                 INT_OFF;
11159                 cmdp = cmdlookup(name, 1);
11160                 cmdp->cmdtype = CMDNORMAL;
11161                 cmdp->param.index = idx;
11162                 INT_ON;
11163                 goto success;
11164         }
11165
11166         /* We failed.  If there was an entry for this command, delete it */
11167         if (cmdp && updatetbl)
11168                 delete_cmd_entry();
11169         if (act & DO_ERR)
11170                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11171         entry->cmdtype = CMDUNKNOWN;
11172         return;
11173
11174  builtin_success:
11175         if (!updatetbl) {
11176                 entry->cmdtype = CMDBUILTIN;
11177                 entry->u.cmd = bcmd;
11178                 return;
11179         }
11180         INT_OFF;
11181         cmdp = cmdlookup(name, 1);
11182         cmdp->cmdtype = CMDBUILTIN;
11183         cmdp->param.cmd = bcmd;
11184         INT_ON;
11185  success:
11186         cmdp->rehash = 0;
11187         entry->cmdtype = cmdp->cmdtype;
11188         entry->u = cmdp->param;
11189 }
11190
11191
11192 /* ============ trap.c */
11193
11194 /*
11195  * The trap builtin.
11196  */
11197 static int
11198 trapcmd(int argc, char **argv)
11199 {
11200         char *action;
11201         char **ap;
11202         int signo;
11203
11204         nextopt(nullstr);
11205         ap = argptr;
11206         if (!*ap) {
11207                 for (signo = 0; signo < NSIG; signo++) {
11208                         if (trap[signo] != NULL) {
11209                                 const char *sn;
11210
11211                                 sn = get_signame(signo);
11212                                 out1fmt("trap -- %s %s\n",
11213                                         single_quote(trap[signo]), sn);
11214                         }
11215                 }
11216                 return 0;
11217         }
11218         if (!ap[1])
11219                 action = NULL;
11220         else
11221                 action = *ap++;
11222         while (*ap) {
11223                 signo = get_signum(*ap);
11224                 if (signo < 0)
11225                         ash_msg_and_raise_error("%s: bad trap", *ap);
11226                 INT_OFF;
11227                 if (action) {
11228                         if (LONE_DASH(action))
11229                                 action = NULL;
11230                         else
11231                                 action = ckstrdup(action);
11232                 }
11233                 if (trap[signo])
11234                         free(trap[signo]);
11235                 trap[signo] = action;
11236                 if (signo != 0)
11237                         setsignal(signo);
11238                 INT_ON;
11239                 ap++;
11240         }
11241         return 0;
11242 }
11243
11244
11245 /* ============ Builtins */
11246
11247 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11248 /*
11249  * Lists available builtins
11250  */
11251 static int
11252 helpcmd(int argc, char **argv)
11253 {
11254         int col, i;
11255
11256         out1fmt("\nBuilt-in commands:\n-------------------\n");
11257         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab) ; i++) {
11258                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11259                                         builtintab[i].name + 1);
11260                 if (col > 60) {
11261                         out1fmt("\n");
11262                         col = 0;
11263                 }
11264         }
11265 #if ENABLE_FEATURE_SH_STANDALONE
11266         for (i = 0; i < NUM_APPLETS; i++) {
11267                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11268                 if (col > 60) {
11269                         out1fmt("\n");
11270                         col = 0;
11271                 }
11272         }
11273 #endif
11274         out1fmt("\n\n");
11275         return EXIT_SUCCESS;
11276 }
11277 #endif /* FEATURE_SH_EXTRA_QUIET */
11278
11279 /*
11280  * The export and readonly commands.
11281  */
11282 static int
11283 exportcmd(int argc, char **argv)
11284 {
11285         struct var *vp;
11286         char *name;
11287         const char *p;
11288         char **aptr;
11289         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11290
11291         if (nextopt("p") != 'p') {
11292                 aptr = argptr;
11293                 name = *aptr;
11294                 if (name) {
11295                         do {
11296                                 p = strchr(name, '=');
11297                                 if (p != NULL) {
11298                                         p++;
11299                                 } else {
11300                                         vp = *findvar(hashvar(name), name);
11301                                         if (vp) {
11302                                                 vp->flags |= flag;
11303                                                 continue;
11304                                         }
11305                                 }
11306                                 setvar(name, p, flag);
11307                         } while ((name = *++aptr) != NULL);
11308                         return 0;
11309                 }
11310         }
11311         showvars(argv[0], flag, 0);
11312         return 0;
11313 }
11314
11315 /*
11316  * Delete a function if it exists.
11317  */
11318 static void
11319 unsetfunc(const char *name)
11320 {
11321         struct tblentry *cmdp;
11322
11323         cmdp = cmdlookup(name, 0);
11324         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11325                 delete_cmd_entry();
11326 }
11327
11328 /*
11329  * The unset builtin command.  We unset the function before we unset the
11330  * variable to allow a function to be unset when there is a readonly variable
11331  * with the same name.
11332  */
11333 static int
11334 unsetcmd(int argc, char **argv)
11335 {
11336         char **ap;
11337         int i;
11338         int flag = 0;
11339         int ret = 0;
11340
11341         while ((i = nextopt("vf")) != '\0') {
11342                 flag = i;
11343         }
11344
11345         for (ap = argptr; *ap; ap++) {
11346                 if (flag != 'f') {
11347                         i = unsetvar(*ap);
11348                         ret |= i;
11349                         if (!(i & 2))
11350                                 continue;
11351                 }
11352                 if (flag != 'v')
11353                         unsetfunc(*ap);
11354         }
11355         return ret & 1;
11356 }
11357
11358
11359 /*      setmode.c      */
11360
11361 #include <sys/times.h>
11362
11363 static const unsigned char timescmd_str[] = {
11364         ' ',  offsetof(struct tms, tms_utime),
11365         '\n', offsetof(struct tms, tms_stime),
11366         ' ',  offsetof(struct tms, tms_cutime),
11367         '\n', offsetof(struct tms, tms_cstime),
11368         0
11369 };
11370
11371 static int
11372 timescmd(int ac, char **av)
11373 {
11374         long clk_tck, s, t;
11375         const unsigned char *p;
11376         struct tms buf;
11377
11378         clk_tck = sysconf(_SC_CLK_TCK);
11379         times(&buf);
11380
11381         p = timescmd_str;
11382         do {
11383                 t = *(clock_t *)(((char *) &buf) + p[1]);
11384                 s = t / clk_tck;
11385                 out1fmt("%ldm%ld.%.3lds%c",
11386                         s/60, s%60,
11387                         ((t - s * clk_tck) * 1000) / clk_tck,
11388                         p[0]);
11389         } while (*(p += 2));
11390
11391         return 0;
11392 }
11393
11394 #if ENABLE_ASH_MATH_SUPPORT
11395 static arith_t
11396 dash_arith(const char *s)
11397 {
11398         arith_t result;
11399         int errcode = 0;
11400
11401         INT_OFF;
11402         result = arith(s, &errcode);
11403         if (errcode < 0) {
11404                 if (errcode == -3)
11405                         ash_msg_and_raise_error("exponent less than 0");
11406                 if (errcode == -2)
11407                         ash_msg_and_raise_error("divide by zero");
11408                 if (errcode == -5)
11409                         ash_msg_and_raise_error("expression recursion loop detected");
11410                 raise_error_syntax(s);
11411         }
11412         INT_ON;
11413
11414         return result;
11415 }
11416
11417 /*
11418  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11419  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11420  *
11421  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11422  */
11423 static int
11424 letcmd(int argc, char **argv)
11425 {
11426         char **ap;
11427         arith_t i = 0;
11428
11429         ap = argv + 1;
11430         if (!*ap)
11431                 ash_msg_and_raise_error("expression expected");
11432         for (ap = argv + 1; *ap; ap++) {
11433                 i = dash_arith(*ap);
11434         }
11435
11436         return !i;
11437 }
11438 #endif /* ASH_MATH_SUPPORT */
11439
11440
11441 /* ============ miscbltin.c
11442  *
11443  * Miscellaneous builtins.
11444  */
11445
11446 #undef rflag
11447
11448 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11449 typedef enum __rlimit_resource rlim_t;
11450 #endif
11451
11452 /*
11453  * The read builtin.  The -e option causes backslashes to escape the
11454  * following character.
11455  *
11456  * This uses unbuffered input, which may be avoidable in some cases.
11457  */
11458 static int
11459 readcmd(int argc, char **argv)
11460 {
11461         char **ap;
11462         int backslash;
11463         char c;
11464         int rflag;
11465         char *prompt;
11466         const char *ifs;
11467         char *p;
11468         int startword;
11469         int status;
11470         int i;
11471 #if ENABLE_ASH_READ_NCHARS
11472         int nch_flag = 0;
11473         int nchars = 0;
11474         int silent = 0;
11475         struct termios tty, old_tty;
11476 #endif
11477 #if ENABLE_ASH_READ_TIMEOUT
11478         fd_set set;
11479         struct timeval ts;
11480
11481         ts.tv_sec = ts.tv_usec = 0;
11482 #endif
11483
11484         rflag = 0;
11485         prompt = NULL;
11486 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11487         while ((i = nextopt("p:rt:n:s")) != '\0')
11488 #elif ENABLE_ASH_READ_NCHARS
11489         while ((i = nextopt("p:rn:s")) != '\0')
11490 #elif ENABLE_ASH_READ_TIMEOUT
11491         while ((i = nextopt("p:rt:")) != '\0')
11492 #else
11493         while ((i = nextopt("p:r")) != '\0')
11494 #endif
11495         {
11496                 switch (i) {
11497                 case 'p':
11498                         prompt = optionarg;
11499                         break;
11500 #if ENABLE_ASH_READ_NCHARS
11501                 case 'n':
11502                         nchars = strtol(optionarg, &p, 10);
11503                         if (*p)
11504                                 ash_msg_and_raise_error("invalid count");
11505                         nch_flag = (nchars > 0);
11506                         break;
11507                 case 's':
11508                         silent = 1;
11509                         break;
11510 #endif
11511 #if ENABLE_ASH_READ_TIMEOUT
11512                 case 't':
11513                         ts.tv_sec = strtol(optionarg, &p, 10);
11514                         ts.tv_usec = 0;
11515                         if (*p == '.') {
11516                                 char *p2;
11517                                 if (*++p) {
11518                                         int scale;
11519                                         ts.tv_usec = strtol(p, &p2, 10);
11520                                         if (*p2)
11521                                                 ash_msg_and_raise_error("invalid timeout");
11522                                         scale = p2 - p;
11523                                         /* normalize to usec */
11524                                         if (scale > 6)
11525                                                 ash_msg_and_raise_error("invalid timeout");
11526                                         while (scale++ < 6)
11527                                                 ts.tv_usec *= 10;
11528                                 }
11529                         } else if (*p) {
11530                                 ash_msg_and_raise_error("invalid timeout");
11531                         }
11532                         if ( ! ts.tv_sec && ! ts.tv_usec)
11533                                 ash_msg_and_raise_error("invalid timeout");
11534                         break;
11535 #endif
11536                 case 'r':
11537                         rflag = 1;
11538                         break;
11539                 default:
11540                         break;
11541                 }
11542         }
11543         if (prompt && isatty(0)) {
11544                 out2str(prompt);
11545         }
11546         ap = argptr;
11547         if (*ap == NULL)
11548                 ash_msg_and_raise_error("arg count");
11549         ifs = bltinlookup("IFS");
11550         if (ifs == NULL)
11551                 ifs = defifs;
11552 #if ENABLE_ASH_READ_NCHARS
11553         if (nch_flag || silent) {
11554                 tcgetattr(0, &tty);
11555                 old_tty = tty;
11556                 if (nch_flag) {
11557                         tty.c_lflag &= ~ICANON;
11558                         tty.c_cc[VMIN] = nchars;
11559                 }
11560                 if (silent) {
11561                         tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11562
11563                 }
11564                 tcsetattr(0, TCSANOW, &tty);
11565         }
11566 #endif
11567 #if ENABLE_ASH_READ_TIMEOUT
11568         if (ts.tv_sec || ts.tv_usec) {
11569                 FD_ZERO(&set);
11570                 FD_SET(0, &set);
11571
11572                 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11573                 if (!i) {
11574 #if ENABLE_ASH_READ_NCHARS
11575                         if (nch_flag)
11576                                 tcsetattr(0, TCSANOW, &old_tty);
11577 #endif
11578                         return 1;
11579                 }
11580         }
11581 #endif
11582         status = 0;
11583         startword = 1;
11584         backslash = 0;
11585         STARTSTACKSTR(p);
11586 #if ENABLE_ASH_READ_NCHARS
11587         while (!nch_flag || nchars--)
11588 #else
11589         for (;;)
11590 #endif
11591         {
11592                 if (read(0, &c, 1) != 1) {
11593                         status = 1;
11594                         break;
11595                 }
11596                 if (c == '\0')
11597                         continue;
11598                 if (backslash) {
11599                         backslash = 0;
11600                         if (c != '\n')
11601                                 goto put;
11602                         continue;
11603                 }
11604                 if (!rflag && c == '\\') {
11605                         backslash++;
11606                         continue;
11607                 }
11608                 if (c == '\n')
11609                         break;
11610                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11611                         continue;
11612                 }
11613                 startword = 0;
11614                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11615                         STACKSTRNUL(p);
11616                         setvar(*ap, stackblock(), 0);
11617                         ap++;
11618                         startword = 1;
11619                         STARTSTACKSTR(p);
11620                 } else {
11621  put:
11622                         STPUTC(c, p);
11623                 }
11624         }
11625 #if ENABLE_ASH_READ_NCHARS
11626         if (nch_flag || silent)
11627                 tcsetattr(0, TCSANOW, &old_tty);
11628 #endif
11629
11630         STACKSTRNUL(p);
11631         /* Remove trailing blanks */
11632         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11633                 *p = '\0';
11634         setvar(*ap, stackblock(), 0);
11635         while (*++ap != NULL)
11636                 setvar(*ap, nullstr, 0);
11637         return status;
11638 }
11639
11640 static int
11641 umaskcmd(int argc, char **argv)
11642 {
11643         static const char permuser[3] = "ugo";
11644         static const char permmode[3] = "rwx";
11645         static const short int permmask[] = {
11646                 S_IRUSR, S_IWUSR, S_IXUSR,
11647                 S_IRGRP, S_IWGRP, S_IXGRP,
11648                 S_IROTH, S_IWOTH, S_IXOTH
11649         };
11650
11651         char *ap;
11652         mode_t mask;
11653         int i;
11654         int symbolic_mode = 0;
11655
11656         while (nextopt("S") != '\0') {
11657                 symbolic_mode = 1;
11658         }
11659
11660         INT_OFF;
11661         mask = umask(0);
11662         umask(mask);
11663         INT_ON;
11664
11665         ap = *argptr;
11666         if (ap == NULL) {
11667                 if (symbolic_mode) {
11668                         char buf[18];
11669                         char *p = buf;
11670
11671                         for (i = 0; i < 3; i++) {
11672                                 int j;
11673
11674                                 *p++ = permuser[i];
11675                                 *p++ = '=';
11676                                 for (j = 0; j < 3; j++) {
11677                                         if ((mask & permmask[3 * i + j]) == 0) {
11678                                                 *p++ = permmode[j];
11679                                         }
11680                                 }
11681                                 *p++ = ',';
11682                         }
11683                         *--p = 0;
11684                         puts(buf);
11685                 } else {
11686                         out1fmt("%.4o\n", mask);
11687                 }
11688         } else {
11689                 if (isdigit((unsigned char) *ap)) {
11690                         mask = 0;
11691                         do {
11692                                 if (*ap >= '8' || *ap < '0')
11693                                         ash_msg_and_raise_error(illnum, argv[1]);
11694                                 mask = (mask << 3) + (*ap - '0');
11695                         } while (*++ap != '\0');
11696                         umask(mask);
11697                 } else {
11698                         mask = ~mask & 0777;
11699                         if (!bb_parse_mode(ap, &mask)) {
11700                                 ash_msg_and_raise_error("illegal mode: %s", ap);
11701                         }
11702                         umask(~mask & 0777);
11703                 }
11704         }
11705         return 0;
11706 }
11707
11708 /*
11709  * ulimit builtin
11710  *
11711  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11712  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11713  * ash by J.T. Conklin.
11714  *
11715  * Public domain.
11716  */
11717
11718 struct limits {
11719         const char *name;
11720         int     cmd;
11721         int     factor; /* multiply by to get rlim_{cur,max} values */
11722         char    option;
11723 };
11724
11725 static const struct limits limits[] = {
11726 #ifdef RLIMIT_CPU
11727         { "time(seconds)",              RLIMIT_CPU,        1, 't' },
11728 #endif
11729 #ifdef RLIMIT_FSIZE
11730         { "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
11731 #endif
11732 #ifdef RLIMIT_DATA
11733         { "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
11734 #endif
11735 #ifdef RLIMIT_STACK
11736         { "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
11737 #endif
11738 #ifdef  RLIMIT_CORE
11739         { "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
11740 #endif
11741 #ifdef RLIMIT_RSS
11742         { "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
11743 #endif
11744 #ifdef RLIMIT_MEMLOCK
11745         { "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
11746 #endif
11747 #ifdef RLIMIT_NPROC
11748         { "process",                    RLIMIT_NPROC,      1, 'p' },
11749 #endif
11750 #ifdef RLIMIT_NOFILE
11751         { "nofiles",                    RLIMIT_NOFILE,     1, 'n' },
11752 #endif
11753 #ifdef RLIMIT_AS
11754         { "vmemory(kbytes)",            RLIMIT_AS,      1024, 'v' },
11755 #endif
11756 #ifdef RLIMIT_LOCKS
11757         { "locks",                      RLIMIT_LOCKS,      1, 'w' },
11758 #endif
11759         { NULL,                         0,                 0,  '\0' }
11760 };
11761
11762 enum limtype { SOFT = 0x1, HARD = 0x2 };
11763
11764 static void
11765 printlim(enum limtype how, const struct rlimit *limit,
11766                         const struct limits *l)
11767 {
11768         rlim_t val;
11769
11770         val = limit->rlim_max;
11771         if (how & SOFT)
11772                 val = limit->rlim_cur;
11773
11774         if (val == RLIM_INFINITY)
11775                 out1fmt("unlimited\n");
11776         else {
11777                 val /= l->factor;
11778                 out1fmt("%lld\n", (long long) val);
11779         }
11780 }
11781
11782 static int
11783 ulimitcmd(int argc, char **argv)
11784 {
11785         int c;
11786         rlim_t val = 0;
11787         enum limtype how = SOFT | HARD;
11788         const struct limits *l;
11789         int set, all = 0;
11790         int optc, what;
11791         struct rlimit limit;
11792
11793         what = 'f';
11794         while ((optc = nextopt("HSa"
11795 #ifdef RLIMIT_CPU
11796                                 "t"
11797 #endif
11798 #ifdef RLIMIT_FSIZE
11799                                 "f"
11800 #endif
11801 #ifdef RLIMIT_DATA
11802                                 "d"
11803 #endif
11804 #ifdef RLIMIT_STACK
11805                                 "s"
11806 #endif
11807 #ifdef RLIMIT_CORE
11808                                 "c"
11809 #endif
11810 #ifdef RLIMIT_RSS
11811                                 "m"
11812 #endif
11813 #ifdef RLIMIT_MEMLOCK
11814                                 "l"
11815 #endif
11816 #ifdef RLIMIT_NPROC
11817                                 "p"
11818 #endif
11819 #ifdef RLIMIT_NOFILE
11820                                 "n"
11821 #endif
11822 #ifdef RLIMIT_AS
11823                                 "v"
11824 #endif
11825 #ifdef RLIMIT_LOCKS
11826                                 "w"
11827 #endif
11828                                         )) != '\0')
11829                 switch (optc) {
11830                 case 'H':
11831                         how = HARD;
11832                         break;
11833                 case 'S':
11834                         how = SOFT;
11835                         break;
11836                 case 'a':
11837                         all = 1;
11838                         break;
11839                 default:
11840                         what = optc;
11841                 }
11842
11843         for (l = limits; l->option != what; l++)
11844                 ;
11845
11846         set = *argptr ? 1 : 0;
11847         if (set) {
11848                 char *p = *argptr;
11849
11850                 if (all || argptr[1])
11851                         ash_msg_and_raise_error("too many arguments");
11852                 if (strncmp(p, "unlimited\n", 9) == 0)
11853                         val = RLIM_INFINITY;
11854                 else {
11855                         val = (rlim_t) 0;
11856
11857                         while ((c = *p++) >= '0' && c <= '9') {
11858                                 val = (val * 10) + (long)(c - '0');
11859                                 if (val < (rlim_t) 0)
11860                                         break;
11861                         }
11862                         if (c)
11863                                 ash_msg_and_raise_error("bad number");
11864                         val *= l->factor;
11865                 }
11866         }
11867         if (all) {
11868                 for (l = limits; l->name; l++) {
11869                         getrlimit(l->cmd, &limit);
11870                         out1fmt("%-20s ", l->name);
11871                         printlim(how, &limit, l);
11872                 }
11873                 return 0;
11874         }
11875
11876         getrlimit(l->cmd, &limit);
11877         if (set) {
11878                 if (how & HARD)
11879                         limit.rlim_max = val;
11880                 if (how & SOFT)
11881                         limit.rlim_cur = val;
11882                 if (setrlimit(l->cmd, &limit) < 0)
11883                         ash_msg_and_raise_error("error setting limit (%m)");
11884         } else {
11885                 printlim(how, &limit, l);
11886         }
11887         return 0;
11888 }
11889
11890
11891 /* ============ Math support */
11892
11893 #if ENABLE_ASH_MATH_SUPPORT
11894
11895 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
11896
11897    Permission is hereby granted, free of charge, to any person obtaining
11898    a copy of this software and associated documentation files (the
11899    "Software"), to deal in the Software without restriction, including
11900    without limitation the rights to use, copy, modify, merge, publish,
11901    distribute, sublicense, and/or sell copies of the Software, and to
11902    permit persons to whom the Software is furnished to do so, subject to
11903    the following conditions:
11904
11905    The above copyright notice and this permission notice shall be
11906    included in all copies or substantial portions of the Software.
11907
11908    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11909    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11910    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11911    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
11912    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11913    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11914    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11915 */
11916
11917 /* This is my infix parser/evaluator. It is optimized for size, intended
11918  * as a replacement for yacc-based parsers. However, it may well be faster
11919  * than a comparable parser written in yacc. The supported operators are
11920  * listed in #defines below. Parens, order of operations, and error handling
11921  * are supported. This code is thread safe. The exact expression format should
11922  * be that which POSIX specifies for shells. */
11923
11924 /* The code uses a simple two-stack algorithm. See
11925  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
11926  * for a detailed explanation of the infix-to-postfix algorithm on which
11927  * this is based (this code differs in that it applies operators immediately
11928  * to the stack instead of adding them to a queue to end up with an
11929  * expression). */
11930
11931 /* To use the routine, call it with an expression string and error return
11932  * pointer */
11933
11934 /*
11935  * Aug 24, 2001              Manuel Novoa III
11936  *
11937  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
11938  *
11939  * 1) In arith_apply():
11940  *    a) Cached values of *numptr and &(numptr[-1]).
11941  *    b) Removed redundant test for zero denominator.
11942  *
11943  * 2) In arith():
11944  *    a) Eliminated redundant code for processing operator tokens by moving
11945  *       to a table-based implementation.  Also folded handling of parens
11946  *       into the table.
11947  *    b) Combined all 3 loops which called arith_apply to reduce generated
11948  *       code size at the cost of speed.
11949  *
11950  * 3) The following expressions were treated as valid by the original code:
11951  *       1()  ,    0!  ,    1 ( *3 )   .
11952  *    These bugs have been fixed by internally enclosing the expression in
11953  *    parens and then checking that all binary ops and right parens are
11954  *    preceded by a valid expression (NUM_TOKEN).
11955  *
11956  * Note: It may be desirable to replace Aaron's test for whitespace with
11957  * ctype's isspace() if it is used by another busybox applet or if additional
11958  * whitespace chars should be considered.  Look below the "#include"s for a
11959  * precompiler test.
11960  */
11961
11962 /*
11963  * Aug 26, 2001              Manuel Novoa III
11964  *
11965  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
11966  *
11967  * Merge in Aaron's comments previously posted to the busybox list,
11968  * modified slightly to take account of my changes to the code.
11969  *
11970  */
11971
11972 /*
11973  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11974  *
11975  * - allow access to variable,
11976  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
11977  * - realize assign syntax (VAR=expr, +=, *= etc)
11978  * - realize exponentiation (** operator)
11979  * - realize comma separated - expr, expr
11980  * - realise ++expr --expr expr++ expr--
11981  * - realise expr ? expr : expr (but, second expr calculate always)
11982  * - allow hexadecimal and octal numbers
11983  * - was restored loses XOR operator
11984  * - remove one goto label, added three ;-)
11985  * - protect $((num num)) as true zero expr (Manuel`s error)
11986  * - always use special isspace(), see comment from bash ;-)
11987  */
11988
11989 #define arith_isspace(arithval) \
11990         (arithval == ' ' || arithval == '\n' || arithval == '\t')
11991
11992 typedef unsigned char operator;
11993
11994 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
11995  * precedence, and 3 high bits are an ID unique across operators of that
11996  * precedence. The ID portion is so that multiple operators can have the
11997  * same precedence, ensuring that the leftmost one is evaluated first.
11998  * Consider * and /. */
11999
12000 #define tok_decl(prec,id) (((id)<<5)|(prec))
12001 #define PREC(op) ((op) & 0x1F)
12002
12003 #define TOK_LPAREN tok_decl(0,0)
12004
12005 #define TOK_COMMA tok_decl(1,0)
12006
12007 #define TOK_ASSIGN tok_decl(2,0)
12008 #define TOK_AND_ASSIGN tok_decl(2,1)
12009 #define TOK_OR_ASSIGN tok_decl(2,2)
12010 #define TOK_XOR_ASSIGN tok_decl(2,3)
12011 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12012 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12013 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12014 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12015
12016 #define TOK_MUL_ASSIGN tok_decl(3,0)
12017 #define TOK_DIV_ASSIGN tok_decl(3,1)
12018 #define TOK_REM_ASSIGN tok_decl(3,2)
12019
12020 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12021 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12022
12023 /* conditional is right associativity too */
12024 #define TOK_CONDITIONAL tok_decl(4,0)
12025 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12026
12027 #define TOK_OR tok_decl(5,0)
12028
12029 #define TOK_AND tok_decl(6,0)
12030
12031 #define TOK_BOR tok_decl(7,0)
12032
12033 #define TOK_BXOR tok_decl(8,0)
12034
12035 #define TOK_BAND tok_decl(9,0)
12036
12037 #define TOK_EQ tok_decl(10,0)
12038 #define TOK_NE tok_decl(10,1)
12039
12040 #define TOK_LT tok_decl(11,0)
12041 #define TOK_GT tok_decl(11,1)
12042 #define TOK_GE tok_decl(11,2)
12043 #define TOK_LE tok_decl(11,3)
12044
12045 #define TOK_LSHIFT tok_decl(12,0)
12046 #define TOK_RSHIFT tok_decl(12,1)
12047
12048 #define TOK_ADD tok_decl(13,0)
12049 #define TOK_SUB tok_decl(13,1)
12050
12051 #define TOK_MUL tok_decl(14,0)
12052 #define TOK_DIV tok_decl(14,1)
12053 #define TOK_REM tok_decl(14,2)
12054
12055 /* exponent is right associativity */
12056 #define TOK_EXPONENT tok_decl(15,1)
12057
12058 /* For now unary operators. */
12059 #define UNARYPREC 16
12060 #define TOK_BNOT tok_decl(UNARYPREC,0)
12061 #define TOK_NOT tok_decl(UNARYPREC,1)
12062
12063 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12064 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12065
12066 #define PREC_PRE (UNARYPREC+2)
12067
12068 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12069 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12070
12071 #define PREC_POST (UNARYPREC+3)
12072
12073 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12074 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12075
12076 #define SPEC_PREC (UNARYPREC+4)
12077
12078 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12079 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12080
12081 #define NUMPTR (*numstackptr)
12082
12083 static int
12084 tok_have_assign(operator op)
12085 {
12086         operator prec = PREC(op);
12087
12088         convert_prec_is_assing(prec);
12089         return (prec == PREC(TOK_ASSIGN) ||
12090                         prec == PREC_PRE || prec == PREC_POST);
12091 }
12092
12093 static int
12094 is_right_associativity(operator prec)
12095 {
12096         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12097                 || prec == PREC(TOK_CONDITIONAL));
12098 }
12099
12100 typedef struct ARITCH_VAR_NUM {
12101         arith_t val;
12102         arith_t contidional_second_val;
12103         char contidional_second_val_initialized;
12104         char *var;      /* if NULL then is regular number,
12105                            else is variable name */
12106 } v_n_t;
12107
12108 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12109         const char *var;
12110         struct CHK_VAR_RECURSIVE_LOOPED *next;
12111 } chk_var_recursive_looped_t;
12112
12113 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12114
12115 static int
12116 arith_lookup_val(v_n_t *t)
12117 {
12118         if (t->var) {
12119                 const char * p = lookupvar(t->var);
12120
12121                 if (p) {
12122                         int errcode;
12123
12124                         /* recursive try as expression */
12125                         chk_var_recursive_looped_t *cur;
12126                         chk_var_recursive_looped_t cur_save;
12127
12128                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12129                                 if (strcmp(cur->var, t->var) == 0) {
12130                                         /* expression recursion loop detected */
12131                                         return -5;
12132                                 }
12133                         }
12134                         /* save current lookuped var name */
12135                         cur = prev_chk_var_recursive;
12136                         cur_save.var = t->var;
12137                         cur_save.next = cur;
12138                         prev_chk_var_recursive = &cur_save;
12139
12140                         t->val = arith (p, &errcode);
12141                         /* restore previous ptr after recursiving */
12142                         prev_chk_var_recursive = cur;
12143                         return errcode;
12144                 }
12145                 /* allow undefined var as 0 */
12146                 t->val = 0;
12147         }
12148         return 0;
12149 }
12150
12151 /* "applying" a token means performing it on the top elements on the integer
12152  * stack. For a unary operator it will only change the top element, but a
12153  * binary operator will pop two arguments and push a result */
12154 static int
12155 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12156 {
12157         v_n_t *numptr_m1;
12158         arith_t numptr_val, rez;
12159         int ret_arith_lookup_val;
12160
12161         /* There is no operator that can work without arguments */
12162         if (NUMPTR == numstack) goto err;
12163         numptr_m1 = NUMPTR - 1;
12164
12165         /* check operand is var with noninteger value */
12166         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12167         if (ret_arith_lookup_val)
12168                 return ret_arith_lookup_val;
12169
12170         rez = numptr_m1->val;
12171         if (op == TOK_UMINUS)
12172                 rez *= -1;
12173         else if (op == TOK_NOT)
12174                 rez = !rez;
12175         else if (op == TOK_BNOT)
12176                 rez = ~rez;
12177         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12178                 rez++;
12179         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12180                 rez--;
12181         else if (op != TOK_UPLUS) {
12182                 /* Binary operators */
12183
12184                 /* check and binary operators need two arguments */
12185                 if (numptr_m1 == numstack) goto err;
12186
12187                 /* ... and they pop one */
12188                 --NUMPTR;
12189                 numptr_val = rez;
12190                 if (op == TOK_CONDITIONAL) {
12191                         if (! numptr_m1->contidional_second_val_initialized) {
12192                                 /* protect $((expr1 ? expr2)) without ": expr" */
12193                                 goto err;
12194                         }
12195                         rez = numptr_m1->contidional_second_val;
12196                 } else if (numptr_m1->contidional_second_val_initialized) {
12197                         /* protect $((expr1 : expr2)) without "expr ? " */
12198                         goto err;
12199                 }
12200                 numptr_m1 = NUMPTR - 1;
12201                 if (op != TOK_ASSIGN) {
12202                         /* check operand is var with noninteger value for not '=' */
12203                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12204                         if (ret_arith_lookup_val)
12205                                 return ret_arith_lookup_val;
12206                 }
12207                 if (op == TOK_CONDITIONAL) {
12208                         numptr_m1->contidional_second_val = rez;
12209                 }
12210                 rez = numptr_m1->val;
12211                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12212                         rez |= numptr_val;
12213                 else if (op == TOK_OR)
12214                         rez = numptr_val || rez;
12215                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12216                         rez &= numptr_val;
12217                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12218                         rez ^= numptr_val;
12219                 else if (op == TOK_AND)
12220                         rez = rez && numptr_val;
12221                 else if (op == TOK_EQ)
12222                         rez = (rez == numptr_val);
12223                 else if (op == TOK_NE)
12224                         rez = (rez != numptr_val);
12225                 else if (op == TOK_GE)
12226                         rez = (rez >= numptr_val);
12227                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12228                         rez >>= numptr_val;
12229                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12230                         rez <<= numptr_val;
12231                 else if (op == TOK_GT)
12232                         rez = (rez > numptr_val);
12233                 else if (op == TOK_LT)
12234                         rez = (rez < numptr_val);
12235                 else if (op == TOK_LE)
12236                         rez = (rez <= numptr_val);
12237                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12238                         rez *= numptr_val;
12239                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12240                         rez += numptr_val;
12241                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12242                         rez -= numptr_val;
12243                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12244                         rez = numptr_val;
12245                 else if (op == TOK_CONDITIONAL_SEP) {
12246                         if (numptr_m1 == numstack) {
12247                                 /* protect $((expr : expr)) without "expr ? " */
12248                                 goto err;
12249                         }
12250                         numptr_m1->contidional_second_val_initialized = op;
12251                         numptr_m1->contidional_second_val = numptr_val;
12252                 } else if (op == TOK_CONDITIONAL) {
12253                         rez = rez ?
12254                                 numptr_val : numptr_m1->contidional_second_val;
12255                 } else if (op == TOK_EXPONENT) {
12256                         if (numptr_val < 0)
12257                                 return -3;      /* exponent less than 0 */
12258                         else {
12259                                 arith_t c = 1;
12260
12261                                 if (numptr_val)
12262                                         while (numptr_val--)
12263                                                 c *= rez;
12264                                 rez = c;
12265                         }
12266                 } else if (numptr_val==0)          /* zero divisor check */
12267                         return -2;
12268                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12269                         rez /= numptr_val;
12270                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12271                         rez %= numptr_val;
12272         }
12273         if (tok_have_assign(op)) {
12274                 char buf[sizeof(arith_t_type)*3 + 2];
12275
12276                 if (numptr_m1->var == NULL) {
12277                         /* Hmm, 1=2 ? */
12278                         goto err;
12279                 }
12280                 /* save to shell variable */
12281 #if ENABLE_ASH_MATH_SUPPORT_64
12282                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12283 #else
12284                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12285 #endif
12286                 setvar(numptr_m1->var, buf, 0);
12287                 /* after saving, make previous value for v++ or v-- */
12288                 if (op == TOK_POST_INC)
12289                         rez--;
12290                 else if (op == TOK_POST_DEC)
12291                         rez++;
12292         }
12293         numptr_m1->val = rez;
12294         /* protect geting var value, is number now */
12295         numptr_m1->var = NULL;
12296         return 0;
12297  err:
12298         return -1;
12299 }
12300
12301 /* longest must be first */
12302 static const char op_tokens[] = {
12303         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12304         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12305         '<','<',    0, TOK_LSHIFT,
12306         '>','>',    0, TOK_RSHIFT,
12307         '|','|',    0, TOK_OR,
12308         '&','&',    0, TOK_AND,
12309         '!','=',    0, TOK_NE,
12310         '<','=',    0, TOK_LE,
12311         '>','=',    0, TOK_GE,
12312         '=','=',    0, TOK_EQ,
12313         '|','=',    0, TOK_OR_ASSIGN,
12314         '&','=',    0, TOK_AND_ASSIGN,
12315         '*','=',    0, TOK_MUL_ASSIGN,
12316         '/','=',    0, TOK_DIV_ASSIGN,
12317         '%','=',    0, TOK_REM_ASSIGN,
12318         '+','=',    0, TOK_PLUS_ASSIGN,
12319         '-','=',    0, TOK_MINUS_ASSIGN,
12320         '-','-',    0, TOK_POST_DEC,
12321         '^','=',    0, TOK_XOR_ASSIGN,
12322         '+','+',    0, TOK_POST_INC,
12323         '*','*',    0, TOK_EXPONENT,
12324         '!',        0, TOK_NOT,
12325         '<',        0, TOK_LT,
12326         '>',        0, TOK_GT,
12327         '=',        0, TOK_ASSIGN,
12328         '|',        0, TOK_BOR,
12329         '&',        0, TOK_BAND,
12330         '*',        0, TOK_MUL,
12331         '/',        0, TOK_DIV,
12332         '%',        0, TOK_REM,
12333         '+',        0, TOK_ADD,
12334         '-',        0, TOK_SUB,
12335         '^',        0, TOK_BXOR,
12336         /* uniq */
12337         '~',        0, TOK_BNOT,
12338         ',',        0, TOK_COMMA,
12339         '?',        0, TOK_CONDITIONAL,
12340         ':',        0, TOK_CONDITIONAL_SEP,
12341         ')',        0, TOK_RPAREN,
12342         '(',        0, TOK_LPAREN,
12343         0
12344 };
12345 /* ptr to ")" */
12346 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12347
12348 static arith_t
12349 arith(const char *expr, int *perrcode)
12350 {
12351         char arithval; /* Current character under analysis */
12352         operator lasttok, op;
12353         operator prec;
12354
12355         const char *p = endexpression;
12356         int errcode;
12357
12358         size_t datasizes = strlen(expr) + 2;
12359
12360         /* Stack of integers */
12361         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12362          * in any given correct or incorrect expression is left as an exercise to
12363          * the reader. */
12364         v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12365                                 *numstackptr = numstack;
12366         /* Stack of operator tokens */
12367         operator *stack = alloca((datasizes) * sizeof(operator)),
12368                                 *stackptr = stack;
12369
12370         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
12371         *perrcode = errcode = 0;
12372
12373         while (1) {
12374                 arithval = *expr;
12375                 if (arithval == 0) {
12376                         if (p == endexpression) {
12377                                 /* Null expression. */
12378                                 return 0;
12379                         }
12380
12381                         /* This is only reached after all tokens have been extracted from the
12382                          * input stream. If there are still tokens on the operator stack, they
12383                          * are to be applied in order. At the end, there should be a final
12384                          * result on the integer stack */
12385
12386                         if (expr != endexpression + 1) {
12387                                 /* If we haven't done so already, */
12388                                 /* append a closing right paren */
12389                                 expr = endexpression;
12390                                 /* and let the loop process it. */
12391                                 continue;
12392                         }
12393                         /* At this point, we're done with the expression. */
12394                         if (numstackptr != numstack+1) {
12395                                 /* ... but if there isn't, it's bad */
12396  err:
12397                                 return (*perrcode = -1);
12398                         }
12399                         if (numstack->var) {
12400                                 /* expression is $((var)) only, lookup now */
12401                                 errcode = arith_lookup_val(numstack);
12402                         }
12403  ret:
12404                         *perrcode = errcode;
12405                         return numstack->val;
12406                 }
12407
12408                 /* Continue processing the expression. */
12409                 if (arith_isspace(arithval)) {
12410                         /* Skip whitespace */
12411                         goto prologue;
12412                 }
12413                 p = endofname(expr);
12414                 if (p != expr) {
12415                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
12416
12417                         numstackptr->var = alloca(var_name_size);
12418                         safe_strncpy(numstackptr->var, expr, var_name_size);
12419                         expr = p;
12420  num:
12421                         numstackptr->contidional_second_val_initialized = 0;
12422                         numstackptr++;
12423                         lasttok = TOK_NUM;
12424                         continue;
12425                 }
12426                 if (isdigit(arithval)) {
12427                         numstackptr->var = NULL;
12428 #if ENABLE_ASH_MATH_SUPPORT_64
12429                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
12430 #else
12431                         numstackptr->val = strtol(expr, (char **) &expr, 0);
12432 #endif
12433                         goto num;
12434                 }
12435                 for (p = op_tokens; ; p++) {
12436                         const char *o;
12437
12438                         if (*p == 0) {
12439                                 /* strange operator not found */
12440                                 goto err;
12441                         }
12442                         for (o = expr; *p && *o == *p; p++)
12443                                 o++;
12444                         if (! *p) {
12445                                 /* found */
12446                                 expr = o - 1;
12447                                 break;
12448                         }
12449                         /* skip tail uncompared token */
12450                         while (*p)
12451                                 p++;
12452                         /* skip zero delim */
12453                         p++;
12454                 }
12455                 op = p[1];
12456
12457                 /* post grammar: a++ reduce to num */
12458                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12459                         lasttok = TOK_NUM;
12460
12461                 /* Plus and minus are binary (not unary) _only_ if the last
12462                  * token was as number, or a right paren (which pretends to be
12463                  * a number, since it evaluates to one). Think about it.
12464                  * It makes sense. */
12465                 if (lasttok != TOK_NUM) {
12466                         switch (op) {
12467                         case TOK_ADD:
12468                                 op = TOK_UPLUS;
12469                                 break;
12470                         case TOK_SUB:
12471                                 op = TOK_UMINUS;
12472                                 break;
12473                         case TOK_POST_INC:
12474                                 op = TOK_PRE_INC;
12475                                 break;
12476                         case TOK_POST_DEC:
12477                                 op = TOK_PRE_DEC;
12478                                 break;
12479                         }
12480                 }
12481                 /* We don't want a unary operator to cause recursive descent on the
12482                  * stack, because there can be many in a row and it could cause an
12483                  * operator to be evaluated before its argument is pushed onto the
12484                  * integer stack. */
12485                 /* But for binary operators, "apply" everything on the operator
12486                  * stack until we find an operator with a lesser priority than the
12487                  * one we have just extracted. */
12488                 /* Left paren is given the lowest priority so it will never be
12489                  * "applied" in this way.
12490                  * if associativity is right and priority eq, applied also skip
12491                  */
12492                 prec = PREC(op);
12493                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12494                         /* not left paren or unary */
12495                         if (lasttok != TOK_NUM) {
12496                                 /* binary op must be preceded by a num */
12497                                 goto err;
12498                         }
12499                         while (stackptr != stack) {
12500                                 if (op == TOK_RPAREN) {
12501                                         /* The algorithm employed here is simple: while we don't
12502                                          * hit an open paren nor the bottom of the stack, pop
12503                                          * tokens and apply them */
12504                                         if (stackptr[-1] == TOK_LPAREN) {
12505                                                 --stackptr;
12506                                                 /* Any operator directly after a */
12507                                                 lasttok = TOK_NUM;
12508                                                 /* close paren should consider itself binary */
12509                                                 goto prologue;
12510                                         }
12511                                 } else {
12512                                         operator prev_prec = PREC(stackptr[-1]);
12513
12514                                         convert_prec_is_assing(prec);
12515                                         convert_prec_is_assing(prev_prec);
12516                                         if (prev_prec < prec)
12517                                                 break;
12518                                         /* check right assoc */
12519                                         if (prev_prec == prec && is_right_associativity(prec))
12520                                                 break;
12521                                 }
12522                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12523                                 if (errcode) goto ret;
12524                         }
12525                         if (op == TOK_RPAREN) {
12526                                 goto err;
12527                         }
12528                 }
12529
12530                 /* Push this operator to the stack and remember it. */
12531                 *stackptr++ = lasttok = op;
12532  prologue:
12533                 ++expr;
12534         } /* while */
12535 }
12536 #endif /* ASH_MATH_SUPPORT */
12537
12538
12539 /* ============ main() and helpers */
12540
12541 /*
12542  * Called to exit the shell.
12543  */
12544 static void exitshell(void) ATTRIBUTE_NORETURN;
12545 static void
12546 exitshell(void)
12547 {
12548         struct jmploc loc;
12549         char *p;
12550         int status;
12551
12552         status = exitstatus;
12553         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12554         if (setjmp(loc.loc)) {
12555                 if (exception == EXEXIT)
12556 /* dash bug: it just does _exit(exitstatus) here
12557  * but we have to do setjobctl(0) first!
12558  * (bug is still not fixed in dash-0.5.3 - if you run dash
12559  * under Midnight Commander, on exit from dash MC is backgrounded) */
12560                         status = exitstatus;
12561                 goto out;
12562         }
12563         exception_handler = &loc;
12564         p = trap[0];
12565         if (p) {
12566                 trap[0] = NULL;
12567                 evalstring(p, 0);
12568         }
12569         flush_stdout_stderr();
12570  out:
12571         setjobctl(0);
12572         _exit(status);
12573         /* NOTREACHED */
12574 }
12575
12576 static void
12577 init(void)
12578 {
12579         /* from input.c: */
12580         basepf.nextc = basepf.buf = basebuf;
12581
12582         /* from trap.c: */
12583         signal(SIGCHLD, SIG_DFL);
12584
12585         /* from var.c: */
12586         {
12587                 char **envp;
12588                 char ppid[sizeof(int)*3 + 1];
12589                 const char *p;
12590                 struct stat st1, st2;
12591
12592                 initvar();
12593                 for (envp = environ; envp && *envp; envp++) {
12594                         if (strchr(*envp, '=')) {
12595                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12596                         }
12597                 }
12598
12599                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12600                 setvar("PPID", ppid, 0);
12601
12602                 p = lookupvar("PWD");
12603                 if (p)
12604                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12605                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12606                                 p = '\0';
12607                 setpwd(p, 0);
12608         }
12609 }
12610
12611 /*
12612  * Process the shell command line arguments.
12613  */
12614 static void
12615 procargs(int argc, char **argv)
12616 {
12617         int i;
12618         const char *xminusc;
12619         char **xargv;
12620
12621         xargv = argv;
12622         arg0 = xargv[0];
12623         if (argc > 0)
12624                 xargv++;
12625         for (i = 0; i < NOPTS; i++)
12626                 optlist[i] = 2;
12627         argptr = xargv;
12628         options(1);
12629         xargv = argptr;
12630         xminusc = minusc;
12631         if (*xargv == NULL) {
12632                 if (xminusc)
12633                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12634                 sflag = 1;
12635         }
12636         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12637                 iflag = 1;
12638         if (mflag == 2)
12639                 mflag = iflag;
12640         for (i = 0; i < NOPTS; i++)
12641                 if (optlist[i] == 2)
12642                         optlist[i] = 0;
12643 #if DEBUG == 2
12644         debug = 1;
12645 #endif
12646         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12647         if (xminusc) {
12648                 minusc = *xargv++;
12649                 if (*xargv)
12650                         goto setarg0;
12651         } else if (!sflag) {
12652                 setinputfile(*xargv, 0);
12653  setarg0:
12654                 arg0 = *xargv++;
12655                 commandname = arg0;
12656         }
12657
12658         shellparam.p = xargv;
12659 #if ENABLE_ASH_GETOPTS
12660         shellparam.optind = 1;
12661         shellparam.optoff = -1;
12662 #endif
12663         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12664         while (*xargv) {
12665                 shellparam.nparam++;
12666                 xargv++;
12667         }
12668         optschanged();
12669 }
12670
12671 /*
12672  * Read /etc/profile or .profile.
12673  */
12674 static void
12675 read_profile(const char *name)
12676 {
12677         int skip;
12678
12679         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12680                 return;
12681         skip = cmdloop(0);
12682         popfile();
12683         if (skip)
12684                 exitshell();
12685 }
12686
12687 /*
12688  * This routine is called when an error or an interrupt occurs in an
12689  * interactive shell and control is returned to the main command loop.
12690  */
12691 static void
12692 reset(void)
12693 {
12694         /* from eval.c: */
12695         evalskip = 0;
12696         loopnest = 0;
12697         /* from input.c: */
12698         parselleft = parsenleft = 0;      /* clear input buffer */
12699         popallfiles();
12700         /* from parser.c: */
12701         tokpushback = 0;
12702         checkkwd = 0;
12703         /* from redir.c: */
12704         clearredir(0);
12705 }
12706
12707 #if PROFILE
12708 static short profile_buf[16384];
12709 extern int etext();
12710 #endif
12711
12712 /*
12713  * Main routine.  We initialize things, parse the arguments, execute
12714  * profiles if we're a login shell, and then call cmdloop to execute
12715  * commands.  The setjmp call sets up the location to jump to when an
12716  * exception occurs.  When an exception occurs the variable "state"
12717  * is used to figure out how far we had gotten.
12718  */
12719 int ash_main(int argc, char **argv);
12720 int ash_main(int argc, char **argv)
12721 {
12722         char *shinit;
12723         volatile int state;
12724         struct jmploc jmploc;
12725         struct stackmark smark;
12726
12727 #if PROFILE
12728         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12729 #endif
12730
12731 #if ENABLE_FEATURE_EDITING
12732         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12733 #endif
12734         state = 0;
12735         if (setjmp(jmploc.loc)) {
12736                 int e;
12737                 int s;
12738
12739                 reset();
12740
12741                 e = exception;
12742                 if (e == EXERROR)
12743                         exitstatus = 2;
12744                 s = state;
12745                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12746                         exitshell();
12747
12748                 if (e == EXINT) {
12749                         outcslow('\n', stderr);
12750                 }
12751                 popstackmark(&smark);
12752                 FORCE_INT_ON; /* enable interrupts */
12753                 if (s == 1)
12754                         goto state1;
12755                 if (s == 2)
12756                         goto state2;
12757                 if (s == 3)
12758                         goto state3;
12759                 goto state4;
12760         }
12761         exception_handler = &jmploc;
12762 #if DEBUG
12763         opentrace();
12764         trace_puts("Shell args: ");
12765         trace_puts_args(argv);
12766 #endif
12767         rootpid = getpid();
12768
12769 #if ENABLE_ASH_RANDOM_SUPPORT
12770         rseed = rootpid + time(NULL);
12771 #endif
12772         init();
12773         setstackmark(&smark);
12774         procargs(argc, argv);
12775 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12776         if (iflag) {
12777                 const char *hp = lookupvar("HISTFILE");
12778
12779                 if (hp == NULL) {
12780                         hp = lookupvar("HOME");
12781                         if (hp != NULL) {
12782                                 char *defhp = concat_path_file(hp, ".ash_history");
12783                                 setvar("HISTFILE", defhp, 0);
12784                                 free(defhp);
12785                         }
12786                 }
12787         }
12788 #endif
12789         if (argv[0] && argv[0][0] == '-')
12790                 isloginsh = 1;
12791         if (isloginsh) {
12792                 state = 1;
12793                 read_profile("/etc/profile");
12794  state1:
12795                 state = 2;
12796                 read_profile(".profile");
12797         }
12798  state2:
12799         state = 3;
12800         if (
12801 #ifndef linux
12802          getuid() == geteuid() && getgid() == getegid() &&
12803 #endif
12804          iflag
12805         ) {
12806                 shinit = lookupvar("ENV");
12807                 if (shinit != NULL && *shinit != '\0') {
12808                         read_profile(shinit);
12809                 }
12810         }
12811  state3:
12812         state = 4;
12813         if (minusc)
12814                 evalstring(minusc, 0);
12815
12816         if (sflag || minusc == NULL) {
12817 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12818                 if ( iflag ) {
12819                         const char *hp = lookupvar("HISTFILE");
12820
12821                         if (hp != NULL)
12822                                 line_input_state->hist_file = hp;
12823                 }
12824 #endif
12825  state4: /* XXX ??? - why isn't this before the "if" statement */
12826                 cmdloop(1);
12827         }
12828 #if PROFILE
12829         monitor(0);
12830 #endif
12831 #ifdef GPROF
12832         {
12833                 extern void _mcleanup(void);
12834                 _mcleanup();
12835         }
12836 #endif
12837         exitshell();
12838         /* NOTREACHED */
12839 }
12840
12841 #if DEBUG
12842 const char *applet_name = "debug stuff usage";
12843 int main(int argc, char **argv)
12844 {
12845         return ash_main(argc, argv);
12846 }
12847 #endif
12848
12849
12850 /*-
12851  * Copyright (c) 1989, 1991, 1993, 1994
12852  *      The Regents of the University of California.  All rights reserved.
12853  *
12854  * This code is derived from software contributed to Berkeley by
12855  * Kenneth Almquist.
12856  *
12857  * Redistribution and use in source and binary forms, with or without
12858  * modification, are permitted provided that the following conditions
12859  * are met:
12860  * 1. Redistributions of source code must retain the above copyright
12861  *    notice, this list of conditions and the following disclaimer.
12862  * 2. Redistributions in binary form must reproduce the above copyright
12863  *    notice, this list of conditions and the following disclaimer in the
12864  *    documentation and/or other materials provided with the distribution.
12865  * 3. Neither the name of the University nor the names of its contributors
12866  *    may be used to endorse or promote products derived from this software
12867  *    without specific prior written permission.
12868  *
12869  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12870  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12871  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12872  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12873  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12874  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12875  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12876  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12877  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12878  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12879  * SUCH DAMAGE.
12880  */