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