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