ash: remove erroneously applied patch
[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 smallint doprompt;                   /* if set, prompt the user */
2156 static smallint needprompt;                 /* true if interactive and at start of line */
2157
2158 #if ENABLE_FEATURE_EDITING
2159 static line_input_t *line_input_state;
2160 static const char *cmdedit_prompt;
2161 static void
2162 putprompt(const char *s)
2163 {
2164         if (ENABLE_ASH_EXPAND_PRMT) {
2165                 free((char*)cmdedit_prompt);
2166                 cmdedit_prompt = ckstrdup(s);
2167                 return;
2168         }
2169         cmdedit_prompt = s;
2170 }
2171 #else
2172 static void
2173 putprompt(const char *s)
2174 {
2175         out2str(s);
2176 }
2177 #endif
2178
2179 #if ENABLE_ASH_EXPAND_PRMT
2180 /* expandstr() needs parsing machinery, so it is far away ahead... */
2181 static const char *expandstr(const char *ps);
2182 #else
2183 #define expandstr(s) s
2184 #endif
2185
2186 static void
2187 setprompt(int whichprompt)
2188 {
2189         const char *prompt;
2190 #if ENABLE_ASH_EXPAND_PRMT
2191         struct stackmark smark;
2192 #endif
2193
2194         needprompt = 0;
2195
2196         switch (whichprompt) {
2197         case 1:
2198                 prompt = ps1val();
2199                 break;
2200         case 2:
2201                 prompt = ps2val();
2202                 break;
2203         default:                        /* 0 */
2204                 prompt = nullstr;
2205         }
2206 #if ENABLE_ASH_EXPAND_PRMT
2207         setstackmark(&smark);
2208         stalloc(stackblocksize());
2209 #endif
2210         putprompt(expandstr(prompt));
2211 #if ENABLE_ASH_EXPAND_PRMT
2212         popstackmark(&smark);
2213 #endif
2214 }
2215
2216
2217 /* ============ The cd and pwd commands */
2218
2219 #define CD_PHYSICAL 1
2220 #define CD_PRINT 2
2221
2222 static int docd(const char *, int);
2223
2224 static char *curdir = nullstr;          /* current working directory */
2225 static char *physdir = nullstr;         /* physical working directory */
2226
2227 static int
2228 cdopt(void)
2229 {
2230         int flags = 0;
2231         int i, j;
2232
2233         j = 'L';
2234         while ((i = nextopt("LP"))) {
2235                 if (i != j) {
2236                         flags ^= CD_PHYSICAL;
2237                         j = i;
2238                 }
2239         }
2240
2241         return flags;
2242 }
2243
2244 /*
2245  * Update curdir (the name of the current directory) in response to a
2246  * cd command.
2247  */
2248 static const char *
2249 updatepwd(const char *dir)
2250 {
2251         char *new;
2252         char *p;
2253         char *cdcomppath;
2254         const char *lim;
2255
2256         cdcomppath = ststrdup(dir);
2257         STARTSTACKSTR(new);
2258         if (*dir != '/') {
2259                 if (curdir == nullstr)
2260                         return 0;
2261                 new = stack_putstr(curdir, new);
2262         }
2263         new = makestrspace(strlen(dir) + 2, new);
2264         lim = stackblock() + 1;
2265         if (*dir != '/') {
2266                 if (new[-1] != '/')
2267                         USTPUTC('/', new);
2268                 if (new > lim && *lim == '/')
2269                         lim++;
2270         } else {
2271                 USTPUTC('/', new);
2272                 cdcomppath++;
2273                 if (dir[1] == '/' && dir[2] != '/') {
2274                         USTPUTC('/', new);
2275                         cdcomppath++;
2276                         lim++;
2277                 }
2278         }
2279         p = strtok(cdcomppath, "/");
2280         while (p) {
2281                 switch (*p) {
2282                 case '.':
2283                         if (p[1] == '.' && p[2] == '\0') {
2284                                 while (new > lim) {
2285                                         STUNPUTC(new);
2286                                         if (new[-1] == '/')
2287                                                 break;
2288                                 }
2289                                 break;
2290                         }
2291                         if (p[1] == '\0')
2292                                 break;
2293                         /* fall through */
2294                 default:
2295                         new = stack_putstr(p, new);
2296                         USTPUTC('/', new);
2297                 }
2298                 p = strtok(0, "/");
2299         }
2300         if (new > lim)
2301                 STUNPUTC(new);
2302         *new = 0;
2303         return stackblock();
2304 }
2305
2306 /*
2307  * Find out what the current directory is. If we already know the current
2308  * directory, this routine returns immediately.
2309  */
2310 static char *
2311 getpwd(void)
2312 {
2313         char *dir = getcwd(0, 0);
2314         return dir ? dir : nullstr;
2315 }
2316
2317 static void
2318 setpwd(const char *val, int setold)
2319 {
2320         char *oldcur, *dir;
2321
2322         oldcur = dir = curdir;
2323
2324         if (setold) {
2325                 setvar("OLDPWD", oldcur, VEXPORT);
2326         }
2327         INT_OFF;
2328         if (physdir != nullstr) {
2329                 if (physdir != oldcur)
2330                         free(physdir);
2331                 physdir = nullstr;
2332         }
2333         if (oldcur == val || !val) {
2334                 char *s = getpwd();
2335                 physdir = s;
2336                 if (!val)
2337                         dir = s;
2338         } else
2339                 dir = ckstrdup(val);
2340         if (oldcur != dir && oldcur != nullstr) {
2341                 free(oldcur);
2342         }
2343         curdir = dir;
2344         INT_ON;
2345         setvar("PWD", dir, VEXPORT);
2346 }
2347
2348 static void hashcd(void);
2349
2350 /*
2351  * Actually do the chdir.  We also call hashcd to let the routines in exec.c
2352  * know that the current directory has changed.
2353  */
2354 static int
2355 docd(const char *dest, int flags)
2356 {
2357         const char *dir = 0;
2358         int err;
2359
2360         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2361
2362         INT_OFF;
2363         if (!(flags & CD_PHYSICAL)) {
2364                 dir = updatepwd(dest);
2365                 if (dir)
2366                         dest = dir;
2367         }
2368         err = chdir(dest);
2369         if (err)
2370                 goto out;
2371         setpwd(dir, 1);
2372         hashcd();
2373  out:
2374         INT_ON;
2375         return err;
2376 }
2377
2378 static int
2379 cdcmd(int argc, char **argv)
2380 {
2381         const char *dest;
2382         const char *path;
2383         const char *p;
2384         char c;
2385         struct stat statb;
2386         int flags;
2387
2388         flags = cdopt();
2389         dest = *argptr;
2390         if (!dest)
2391                 dest = bltinlookup(homestr);
2392         else if (LONE_DASH(dest)) {
2393                 dest = bltinlookup("OLDPWD");
2394                 flags |= CD_PRINT;
2395         }
2396         if (!dest)
2397                 dest = nullstr;
2398         if (*dest == '/')
2399                 goto step7;
2400         if (*dest == '.') {
2401                 c = dest[1];
2402  dotdot:
2403                 switch (c) {
2404                 case '\0':
2405                 case '/':
2406                         goto step6;
2407                 case '.':
2408                         c = dest[2];
2409                         if (c != '.')
2410                                 goto dotdot;
2411                 }
2412         }
2413         if (!*dest)
2414                 dest = ".";
2415         path = bltinlookup("CDPATH");
2416         if (!path) {
2417  step6:
2418  step7:
2419                 p = dest;
2420                 goto docd;
2421         }
2422         do {
2423                 c = *path;
2424                 p = padvance(&path, dest);
2425                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2426                         if (c && c != ':')
2427                                 flags |= CD_PRINT;
2428  docd:
2429                         if (!docd(p, flags))
2430                                 goto out;
2431                         break;
2432                 }
2433         } while (path);
2434         ash_msg_and_raise_error("can't cd to %s", dest);
2435         /* NOTREACHED */
2436  out:
2437         if (flags & CD_PRINT)
2438                 out1fmt(snlfmt, curdir);
2439         return 0;
2440 }
2441
2442 static int
2443 pwdcmd(int argc, char **argv)
2444 {
2445         int flags;
2446         const char *dir = curdir;
2447
2448         flags = cdopt();
2449         if (flags) {
2450                 if (physdir == nullstr)
2451                         setpwd(dir, 0);
2452                 dir = physdir;
2453         }
2454         out1fmt(snlfmt, dir);
2455         return 0;
2456 }
2457
2458
2459 /* ============ ... */
2460
2461 #define IBUFSIZ COMMON_BUFSIZE
2462 #define basebuf bb_common_bufsiz1       /* buffer for top level input file */
2463
2464 /* Syntax classes */
2465 #define CWORD 0                 /* character is nothing special */
2466 #define CNL 1                   /* newline character */
2467 #define CBACK 2                 /* a backslash character */
2468 #define CSQUOTE 3               /* single quote */
2469 #define CDQUOTE 4               /* double quote */
2470 #define CENDQUOTE 5             /* a terminating quote */
2471 #define CBQUOTE 6               /* backwards single quote */
2472 #define CVAR 7                  /* a dollar sign */
2473 #define CENDVAR 8               /* a '}' character */
2474 #define CLP 9                   /* a left paren in arithmetic */
2475 #define CRP 10                  /* a right paren in arithmetic */
2476 #define CENDFILE 11             /* end of file */
2477 #define CCTL 12                 /* like CWORD, except it must be escaped */
2478 #define CSPCL 13                /* these terminate a word */
2479 #define CIGN 14                 /* character should be ignored */
2480
2481 #if ENABLE_ASH_ALIAS
2482 #define SYNBASE 130
2483 #define PEOF -130
2484 #define PEOA -129
2485 #define PEOA_OR_PEOF PEOA
2486 #else
2487 #define SYNBASE 129
2488 #define PEOF -129
2489 #define PEOA_OR_PEOF PEOF
2490 #endif
2491
2492 /* number syntax index */
2493 #define BASESYNTAX 0    /* not in quotes */
2494 #define DQSYNTAX   1    /* in double quotes */
2495 #define SQSYNTAX   2    /* in single quotes */
2496 #define ARISYNTAX  3    /* in arithmetic */
2497
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 static int plinno = 1;                  /* input line number */
8485 /* number of characters left in input buffer */
8486 static int parsenleft;                  /* copy of parsefile->nleft */
8487 static int parselleft;                  /* copy of parsefile->lleft */
8488 /* next character in input buffer */
8489 static char *parsenextc;                /* copy of parsefile->nextc */
8490
8491 static int checkkwd;
8492 /* values of checkkwd variable */
8493 #define CHKALIAS        0x1
8494 #define CHKKWD          0x2
8495 #define CHKNL           0x4
8496
8497 static void
8498 popstring(void)
8499 {
8500         struct strpush *sp = parsefile->strpush;
8501
8502         INT_OFF;
8503 #if ENABLE_ASH_ALIAS
8504         if (sp->ap) {
8505                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8506                         checkkwd |= CHKALIAS;
8507                 }
8508                 if (sp->string != sp->ap->val) {
8509                         free(sp->string);
8510                 }
8511                 sp->ap->flag &= ~ALIASINUSE;
8512                 if (sp->ap->flag & ALIASDEAD) {
8513                         unalias(sp->ap->name);
8514                 }
8515         }
8516 #endif
8517         parsenextc = sp->prevstring;
8518         parsenleft = sp->prevnleft;
8519 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8520         parsefile->strpush = sp->prev;
8521         if (sp != &(parsefile->basestrpush))
8522                 free(sp);
8523         INT_ON;
8524 }
8525
8526 static int
8527 preadfd(void)
8528 {
8529         int nr;
8530         char *buf =  parsefile->buf;
8531         parsenextc = buf;
8532
8533  retry:
8534 #if ENABLE_FEATURE_EDITING
8535         if (!iflag || parsefile->fd)
8536                 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8537         else {
8538 #if ENABLE_FEATURE_TAB_COMPLETION
8539                 line_input_state->path_lookup = pathval();
8540 #endif
8541                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8542                 if (nr == 0) {
8543                         /* Ctrl+C pressed */
8544                         if (trap[SIGINT]) {
8545                                 buf[0] = '\n';
8546                                 buf[1] = '\0';
8547                                 raise(SIGINT);
8548                                 return 1;
8549                         }
8550                         goto retry;
8551                 }
8552                 if (nr < 0 && errno == 0) {
8553                         /* Ctrl+D presend */
8554                         nr = 0;
8555                 }
8556         }
8557 #else
8558         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8559 #endif
8560
8561         if (nr < 0) {
8562                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8563                         int flags = fcntl(0, F_GETFL);
8564                         if (flags >= 0 && flags & O_NONBLOCK) {
8565                                 flags &=~ O_NONBLOCK;
8566                                 if (fcntl(0, F_SETFL, flags) >= 0) {
8567                                         out2str("sh: turning off NDELAY mode\n");
8568                                         goto retry;
8569                                 }
8570                         }
8571                 }
8572         }
8573         return nr;
8574 }
8575
8576 /*
8577  * Refill the input buffer and return the next input character:
8578  *
8579  * 1) If a string was pushed back on the input, pop it;
8580  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8581  *    from a string so we can't refill the buffer, return EOF.
8582  * 3) If the is more stuff in this buffer, use it else call read to fill it.
8583  * 4) Process input up to the next newline, deleting nul characters.
8584  */
8585 static int
8586 preadbuffer(void)
8587 {
8588         char *q;
8589         int more;
8590         char savec;
8591
8592         while (parsefile->strpush) {
8593 #if ENABLE_ASH_ALIAS
8594                 if (parsenleft == -1 && parsefile->strpush->ap &&
8595                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8596                         return PEOA;
8597                 }
8598 #endif
8599                 popstring();
8600                 if (--parsenleft >= 0)
8601                         return signed_char2int(*parsenextc++);
8602         }
8603         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8604                 return PEOF;
8605         flush_stdout_stderr();
8606
8607         more = parselleft;
8608         if (more <= 0) {
8609  again:
8610                 more = preadfd();
8611                 if (more <= 0) {
8612                         parselleft = parsenleft = EOF_NLEFT;
8613                         return PEOF;
8614                 }
8615         }
8616
8617         q = parsenextc;
8618
8619         /* delete nul characters */
8620         for (;;) {
8621                 int c;
8622
8623                 more--;
8624                 c = *q;
8625
8626                 if (!c)
8627                         memmove(q, q + 1, more);
8628                 else {
8629                         q++;
8630                         if (c == '\n') {
8631                                 parsenleft = q - parsenextc - 1;
8632                                 break;
8633                         }
8634                 }
8635
8636                 if (more <= 0) {
8637                         parsenleft = q - parsenextc - 1;
8638                         if (parsenleft < 0)
8639                                 goto again;
8640                         break;
8641                 }
8642         }
8643         parselleft = more;
8644
8645         savec = *q;
8646         *q = '\0';
8647
8648         if (vflag) {
8649                 out2str(parsenextc);
8650         }
8651
8652         *q = savec;
8653
8654         return signed_char2int(*parsenextc++);
8655 }
8656
8657 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8658 static int
8659 pgetc(void)
8660 {
8661         return pgetc_as_macro();
8662 }
8663
8664 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8665 #define pgetc_macro() pgetc()
8666 #else
8667 #define pgetc_macro() pgetc_as_macro()
8668 #endif
8669
8670 /*
8671  * Same as pgetc(), but ignores PEOA.
8672  */
8673 #if ENABLE_ASH_ALIAS
8674 static int
8675 pgetc2(void)
8676 {
8677         int c;
8678
8679         do {
8680                 c = pgetc_macro();
8681         } while (c == PEOA);
8682         return c;
8683 }
8684 #else
8685 static int
8686 pgetc2(void)
8687 {
8688         return pgetc_macro();
8689 }
8690 #endif
8691
8692 /*
8693  * Read a line from the script.
8694  */
8695 static char *
8696 pfgets(char *line, int len)
8697 {
8698         char *p = line;
8699         int nleft = len;
8700         int c;
8701
8702         while (--nleft > 0) {
8703                 c = pgetc2();
8704                 if (c == PEOF) {
8705                         if (p == line)
8706                                 return NULL;
8707                         break;
8708                 }
8709                 *p++ = c;
8710                 if (c == '\n')
8711                         break;
8712         }
8713         *p = '\0';
8714         return line;
8715 }
8716
8717 /*
8718  * Undo the last call to pgetc.  Only one character may be pushed back.
8719  * PEOF may be pushed back.
8720  */
8721 static void
8722 pungetc(void)
8723 {
8724         parsenleft++;
8725         parsenextc--;
8726 }
8727
8728 /*
8729  * Push a string back onto the input at this current parsefile level.
8730  * We handle aliases this way.
8731  */
8732 static void
8733 pushstring(char *s, void *ap)
8734 {
8735         struct strpush *sp;
8736         size_t len;
8737
8738         len = strlen(s);
8739         INT_OFF;
8740 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8741         if (parsefile->strpush) {
8742                 sp = ckmalloc(sizeof(struct strpush));
8743                 sp->prev = parsefile->strpush;
8744                 parsefile->strpush = sp;
8745         } else
8746                 sp = parsefile->strpush = &(parsefile->basestrpush);
8747         sp->prevstring = parsenextc;
8748         sp->prevnleft = parsenleft;
8749 #if ENABLE_ASH_ALIAS
8750         sp->ap = (struct alias *)ap;
8751         if (ap) {
8752                 ((struct alias *)ap)->flag |= ALIASINUSE;
8753                 sp->string = s;
8754         }
8755 #endif
8756         parsenextc = s;
8757         parsenleft = len;
8758         INT_ON;
8759 }
8760
8761 /*
8762  * To handle the "." command, a stack of input files is used.  Pushfile
8763  * adds a new entry to the stack and popfile restores the previous level.
8764  */
8765 static void
8766 pushfile(void)
8767 {
8768         struct parsefile *pf;
8769
8770         parsefile->nleft = parsenleft;
8771         parsefile->lleft = parselleft;
8772         parsefile->nextc = parsenextc;
8773         parsefile->linno = plinno;
8774         pf = ckmalloc(sizeof(*pf));
8775         pf->prev = parsefile;
8776         pf->fd = -1;
8777         pf->strpush = NULL;
8778         pf->basestrpush.prev = NULL;
8779         parsefile = pf;
8780 }
8781
8782 static void
8783 popfile(void)
8784 {
8785         struct parsefile *pf = parsefile;
8786
8787         INT_OFF;
8788         if (pf->fd >= 0)
8789                 close(pf->fd);
8790         if (pf->buf)
8791                 free(pf->buf);
8792         while (pf->strpush)
8793                 popstring();
8794         parsefile = pf->prev;
8795         free(pf);
8796         parsenleft = parsefile->nleft;
8797         parselleft = parsefile->lleft;
8798         parsenextc = parsefile->nextc;
8799         plinno = parsefile->linno;
8800         INT_ON;
8801 }
8802
8803 /*
8804  * Return to top level.
8805  */
8806 static void
8807 popallfiles(void)
8808 {
8809         while (parsefile != &basepf)
8810                 popfile();
8811 }
8812
8813 /*
8814  * Close the file(s) that the shell is reading commands from.  Called
8815  * after a fork is done.
8816  */
8817 static void
8818 closescript(void)
8819 {
8820         popallfiles();
8821         if (parsefile->fd > 0) {
8822                 close(parsefile->fd);
8823                 parsefile->fd = 0;
8824         }
8825 }
8826
8827 /*
8828  * Like setinputfile, but takes an open file descriptor.  Call this with
8829  * interrupts off.
8830  */
8831 static void
8832 setinputfd(int fd, int push)
8833 {
8834         fcntl(fd, F_SETFD, FD_CLOEXEC);
8835         if (push) {
8836                 pushfile();
8837                 parsefile->buf = 0;
8838         }
8839         parsefile->fd = fd;
8840         if (parsefile->buf == NULL)
8841                 parsefile->buf = ckmalloc(IBUFSIZ);
8842         parselleft = parsenleft = 0;
8843         plinno = 1;
8844 }
8845
8846 /*
8847  * Set the input to take input from a file.  If push is set, push the
8848  * old input onto the stack first.
8849  */
8850 static int
8851 setinputfile(const char *fname, int flags)
8852 {
8853         int fd;
8854         int fd2;
8855
8856         INT_OFF;
8857         fd = open(fname, O_RDONLY);
8858         if (fd < 0) {
8859                 if (flags & INPUT_NOFILE_OK)
8860                         goto out;
8861                 ash_msg_and_raise_error("can't open %s", fname);
8862         }
8863         if (fd < 10) {
8864                 fd2 = copyfd(fd, 10);
8865                 close(fd);
8866                 if (fd2 < 0)
8867                         ash_msg_and_raise_error("out of file descriptors");
8868                 fd = fd2;
8869         }
8870         setinputfd(fd, flags & INPUT_PUSH_FILE);
8871  out:
8872         INT_ON;
8873         return fd;
8874 }
8875
8876 /*
8877  * Like setinputfile, but takes input from a string.
8878  */
8879 static void
8880 setinputstring(char *string)
8881 {
8882         INT_OFF;
8883         pushfile();
8884         parsenextc = string;
8885         parsenleft = strlen(string);
8886         parsefile->buf = NULL;
8887         plinno = 1;
8888         INT_ON;
8889 }
8890
8891
8892 /* ============ mail.c
8893  *
8894  * Routines to check for mail.
8895  */
8896
8897 #if ENABLE_ASH_MAIL
8898
8899 #define MAXMBOXES 10
8900
8901 /* times of mailboxes */
8902 static time_t mailtime[MAXMBOXES];
8903 /* Set if MAIL or MAILPATH is changed. */
8904 static smallint mail_var_path_changed;
8905
8906 /*
8907  * Print appropriate message(s) if mail has arrived.
8908  * If mail_var_path_changed is set,
8909  * then the value of MAIL has mail_var_path_changed,
8910  * so we just update the values.
8911  */
8912 static void
8913 chkmail(void)
8914 {
8915         const char *mpath;
8916         char *p;
8917         char *q;
8918         time_t *mtp;
8919         struct stackmark smark;
8920         struct stat statb;
8921
8922         setstackmark(&smark);
8923         mpath = mpathset() ? mpathval() : mailval();
8924         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8925                 p = padvance(&mpath, nullstr);
8926                 if (p == NULL)
8927                         break;
8928                 if (*p == '\0')
8929                         continue;
8930                 for (q = p; *q; q++);
8931 #if DEBUG
8932                 if (q[-1] != '/')
8933                         abort();
8934 #endif
8935                 q[-1] = '\0';                   /* delete trailing '/' */
8936                 if (stat(p, &statb) < 0) {
8937                         *mtp = 0;
8938                         continue;
8939                 }
8940                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8941                         fprintf(
8942                                 stderr, snlfmt,
8943                                 pathopt ? pathopt : "you have mail"
8944                         );
8945                 }
8946                 *mtp = statb.st_mtime;
8947         }
8948         mail_var_path_changed = 0;
8949         popstackmark(&smark);
8950 }
8951
8952 static void
8953 changemail(const char *val)
8954 {
8955         mail_var_path_changed = 1;
8956 }
8957
8958 #endif /* ASH_MAIL */
8959
8960
8961 /* ============ ??? */
8962
8963 /*
8964  * Set the shell parameters.
8965  */
8966 static void
8967 setparam(char **argv)
8968 {
8969         char **newparam;
8970         char **ap;
8971         int nparam;
8972
8973         for (nparam = 0; argv[nparam]; nparam++);
8974         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8975         while (*argv) {
8976                 *ap++ = ckstrdup(*argv++);
8977         }
8978         *ap = NULL;
8979         freeparam(&shellparam);
8980         shellparam.malloc = 1;
8981         shellparam.nparam = nparam;
8982         shellparam.p = newparam;
8983 #if ENABLE_ASH_GETOPTS
8984         shellparam.optind = 1;
8985         shellparam.optoff = -1;
8986 #endif
8987 }
8988
8989 /*
8990  * Process shell options.  The global variable argptr contains a pointer
8991  * to the argument list; we advance it past the options.
8992  */
8993 static void
8994 minus_o(char *name, int val)
8995 {
8996         int i;
8997
8998         if (name) {
8999                 for (i = 0; i < NOPTS; i++) {
9000                         if (strcmp(name, optnames(i)) == 0) {
9001                                 optlist[i] = val;
9002                                 return;
9003                         }
9004                 }
9005                 ash_msg_and_raise_error("illegal option -o %s", name);
9006         }
9007         out1str("Current option settings\n");
9008         for (i = 0; i < NOPTS; i++)
9009                 out1fmt("%-16s%s\n", optnames(i),
9010                                 optlist[i] ? "on" : "off");
9011 }
9012 static void
9013 setoption(int flag, int val)
9014 {
9015         int i;
9016
9017         for (i = 0; i < NOPTS; i++) {
9018                 if (optletters(i) == flag) {
9019                         optlist[i] = val;
9020                         return;
9021                 }
9022         }
9023         ash_msg_and_raise_error("illegal option -%c", flag);
9024         /* NOTREACHED */
9025 }
9026 static void
9027 options(int cmdline)
9028 {
9029         char *p;
9030         int val;
9031         int c;
9032
9033         if (cmdline)
9034                 minusc = NULL;
9035         while ((p = *argptr) != NULL) {
9036                 c = *p++;
9037                 if (c != '-' && c != '+')
9038                         break;
9039                 argptr++;
9040                 val = 0; /* val = 0 if c == '+' */
9041                 if (c == '-') {
9042                         val = 1;
9043                         if (p[0] == '\0' || LONE_DASH(p)) {
9044                                 if (!cmdline) {
9045                                         /* "-" means turn off -x and -v */
9046                                         if (p[0] == '\0')
9047                                                 xflag = vflag = 0;
9048                                         /* "--" means reset params */
9049                                         else if (*argptr == NULL)
9050                                                 setparam(argptr);
9051                                 }
9052                                 break;    /* "-" or  "--" terminates options */
9053                         }
9054                 }
9055                 /* first char was + or - */
9056                 while ((c = *p++) != '\0') {
9057                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9058                         if (c == 'c' && cmdline) {
9059                                 minusc = p;     /* command is after shell args */
9060                         } else if (c == 'o') {
9061                                 minus_o(*argptr, val);
9062                                 if (*argptr)
9063                                         argptr++;
9064                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9065                                 isloginsh = 1;
9066                         /* bash does not accept +-login, we also won't */
9067                         } else if (cmdline && val && (c == '-')) { /* long options */
9068                                 if (strcmp(p, "login") == 0)
9069                                         isloginsh = 1;
9070                                 break;
9071                         } else {
9072                                 setoption(c, val);
9073                         }
9074                 }
9075         }
9076 }
9077
9078 /*
9079  * The shift builtin command.
9080  */
9081 static int
9082 shiftcmd(int argc, char **argv)
9083 {
9084         int n;
9085         char **ap1, **ap2;
9086
9087         n = 1;
9088         if (argc > 1)
9089                 n = number(argv[1]);
9090         if (n > shellparam.nparam)
9091                 ash_msg_and_raise_error("can't shift that many");
9092         INT_OFF;
9093         shellparam.nparam -= n;
9094         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9095                 if (shellparam.malloc)
9096                         free(*ap1);
9097         }
9098         ap2 = shellparam.p;
9099         while ((*ap2++ = *ap1++) != NULL);
9100 #if ENABLE_ASH_GETOPTS
9101         shellparam.optind = 1;
9102         shellparam.optoff = -1;
9103 #endif
9104         INT_ON;
9105         return 0;
9106 }
9107
9108 /*
9109  * POSIX requires that 'set' (but not export or readonly) output the
9110  * variables in lexicographic order - by the locale's collating order (sigh).
9111  * Maybe we could keep them in an ordered balanced binary tree
9112  * instead of hashed lists.
9113  * For now just roll 'em through qsort for printing...
9114  */
9115 static int
9116 showvars(const char *sep_prefix, int on, int off)
9117 {
9118         const char *sep;
9119         char **ep, **epend;
9120
9121         ep = listvars(on, off, &epend);
9122         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9123
9124         sep = *sep_prefix ? " " : sep_prefix;
9125
9126         for (; ep < epend; ep++) {
9127                 const char *p;
9128                 const char *q;
9129
9130                 p = strchrnul(*ep, '=');
9131                 q = nullstr;
9132                 if (*p)
9133                         q = single_quote(++p);
9134                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9135         }
9136         return 0;
9137 }
9138
9139 /*
9140  * The set command builtin.
9141  */
9142 static int
9143 setcmd(int argc, char **argv)
9144 {
9145         if (argc == 1)
9146                 return showvars(nullstr, 0, VUNSET);
9147         INT_OFF;
9148         options(0);
9149         optschanged();
9150         if (*argptr != NULL) {
9151                 setparam(argptr);
9152         }
9153         INT_ON;
9154         return 0;
9155 }
9156
9157 #if ENABLE_ASH_RANDOM_SUPPORT
9158 /* Roughly copied from bash.. */
9159 static void
9160 change_random(const char *value)
9161 {
9162         if (value == NULL) {
9163                 /* "get", generate */
9164                 char buf[16];
9165
9166                 rseed = rseed * 1103515245 + 12345;
9167                 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9168                 /* set without recursion */
9169                 setvar(vrandom.text, buf, VNOFUNC);
9170                 vrandom.flags &= ~VNOFUNC;
9171         } else {
9172                 /* set/reset */
9173                 rseed = strtoul(value, (char **)NULL, 10);
9174         }
9175 }
9176 #endif
9177
9178 #if ENABLE_ASH_GETOPTS
9179 static int
9180 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9181 {
9182         char *p, *q;
9183         char c = '?';
9184         int done = 0;
9185         int err = 0;
9186         char s[12];
9187         char **optnext;
9188
9189         if (*param_optind < 1)
9190                 return 1;
9191         optnext = optfirst + *param_optind - 1;
9192
9193         if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9194                 p = NULL;
9195         else
9196                 p = optnext[-1] + *optoff;
9197         if (p == NULL || *p == '\0') {
9198                 /* Current word is done, advance */
9199                 p = *optnext;
9200                 if (p == NULL || *p != '-' || *++p == '\0') {
9201  atend:
9202                         p = NULL;
9203                         done = 1;
9204                         goto out;
9205                 }
9206                 optnext++;
9207                 if (LONE_DASH(p))        /* check for "--" */
9208                         goto atend;
9209         }
9210
9211         c = *p++;
9212         for (q = optstr; *q != c; ) {
9213                 if (*q == '\0') {
9214                         if (optstr[0] == ':') {
9215                                 s[0] = c;
9216                                 s[1] = '\0';
9217                                 err |= setvarsafe("OPTARG", s, 0);
9218                         } else {
9219                                 fprintf(stderr, "Illegal option -%c\n", c);
9220                                 unsetvar("OPTARG");
9221                         }
9222                         c = '?';
9223                         goto out;
9224                 }
9225                 if (*++q == ':')
9226                         q++;
9227         }
9228
9229         if (*++q == ':') {
9230                 if (*p == '\0' && (p = *optnext) == NULL) {
9231                         if (optstr[0] == ':') {
9232                                 s[0] = c;
9233                                 s[1] = '\0';
9234                                 err |= setvarsafe("OPTARG", s, 0);
9235                                 c = ':';
9236                         } else {
9237                                 fprintf(stderr, "No arg for -%c option\n", c);
9238                                 unsetvar("OPTARG");
9239                                 c = '?';
9240                         }
9241                         goto out;
9242                 }
9243
9244                 if (p == *optnext)
9245                         optnext++;
9246                 err |= setvarsafe("OPTARG", p, 0);
9247                 p = NULL;
9248         } else
9249                 err |= setvarsafe("OPTARG", nullstr, 0);
9250  out:
9251         *optoff = p ? p - *(optnext - 1) : -1;
9252         *param_optind = optnext - optfirst + 1;
9253         fmtstr(s, sizeof(s), "%d", *param_optind);
9254         err |= setvarsafe("OPTIND", s, VNOFUNC);
9255         s[0] = c;
9256         s[1] = '\0';
9257         err |= setvarsafe(optvar, s, 0);
9258         if (err) {
9259                 *param_optind = 1;
9260                 *optoff = -1;
9261                 flush_stdout_stderr();
9262                 raise_exception(EXERROR);
9263         }
9264         return done;
9265 }
9266
9267 /*
9268  * The getopts builtin.  Shellparam.optnext points to the next argument
9269  * to be processed.  Shellparam.optptr points to the next character to
9270  * be processed in the current argument.  If shellparam.optnext is NULL,
9271  * then it's the first time getopts has been called.
9272  */
9273 static int
9274 getoptscmd(int argc, char **argv)
9275 {
9276         char **optbase;
9277
9278         if (argc < 3)
9279                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9280         if (argc == 3) {
9281                 optbase = shellparam.p;
9282                 if (shellparam.optind > shellparam.nparam + 1) {
9283                         shellparam.optind = 1;
9284                         shellparam.optoff = -1;
9285                 }
9286         } else {
9287                 optbase = &argv[3];
9288                 if (shellparam.optind > argc - 2) {
9289                         shellparam.optind = 1;
9290                         shellparam.optoff = -1;
9291                 }
9292         }
9293
9294         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9295                         &shellparam.optoff);
9296 }
9297 #endif /* ASH_GETOPTS */
9298
9299
9300 /* ============ Shell parser */
9301
9302 /*
9303  * NEOF is returned by parsecmd when it encounters an end of file.  It
9304  * must be distinct from NULL, so we use the address of a variable that
9305  * happens to be handy.
9306  */
9307 static smallint tokpushback;           /* last token pushed back */
9308 #define NEOF ((union node *)&tokpushback)
9309 static smallint 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 smallint 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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 #define CHECKEND()      {goto checkend; checkend_return:;}
9870 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
9871 #define PARSESUB()      {goto parsesub; parsesub_return:;}
9872 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9873 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9874 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
9875
9876 static int
9877 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9878 {
9879         /* NB: syntax parameter fits into smallint */
9880         int c = firstc;
9881         char *out;
9882         int len;
9883         char line[EOFMARKLEN + 1];
9884         struct nodelist *bqlist;
9885         smallint quotef;
9886         smallint dblquote;
9887         smallint oldstyle;
9888         smallint prevsyntax; /* syntax before arithmetic */
9889         int varnest;         /* levels of variables expansion */
9890         int arinest;         /* levels of arithmetic expansion */
9891         int parenlevel;      /* levels of parens in arithmetic */
9892         int dqvarnest;       /* levels of variables expansion within double quotes */
9893
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         startlinno = plinno;
9908         bqlist = NULL;
9909         quotef = 0;
9910         dblquote = (syntax == DQSYNTAX);
9911         oldstyle = 0;
9912         prevsyntax = 0;
9913         varnest = 0;
9914         arinest = 0;
9915         parenlevel = 0;
9916         dqvarnest = 0;
9917
9918         STARTSTACKSTR(out);
9919         loop: { /* for each line, until end of word */
9920                 CHECKEND();     /* set c to PEOF if at end of here document */
9921                 for (;;) {      /* until end of line or end of word */
9922                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
9923                         switch (SIT(c, syntax)) {
9924                         case CNL:       /* '\n' */
9925                                 if (syntax == BASESYNTAX)
9926                                         goto endword;   /* exit outer loop */
9927                                 USTPUTC(c, out);
9928                                 plinno++;
9929                                 if (doprompt)
9930                                         setprompt(2);
9931                                 c = pgetc();
9932                                 goto loop;              /* continue outer loop */
9933                         case CWORD:
9934                                 USTPUTC(c, out);
9935                                 break;
9936                         case CCTL:
9937                                 if (eofmark == NULL || dblquote)
9938                                         USTPUTC(CTLESC, out);
9939                                 USTPUTC(c, out);
9940                                 break;
9941                         case CBACK:     /* backslash */
9942                                 c = pgetc2();
9943                                 if (c == PEOF) {
9944                                         USTPUTC(CTLESC, out);
9945                                         USTPUTC('\\', out);
9946                                         pungetc();
9947                                 } else if (c == '\n') {
9948                                         if (doprompt)
9949                                                 setprompt(2);
9950                                 } else {
9951                                         if (dblquote &&
9952                                                 c != '\\' && c != '`' &&
9953                                                 c != '$' && (
9954                                                         c != '"' ||
9955                                                         eofmark != NULL)
9956                                         ) {
9957                                                 USTPUTC(CTLESC, out);
9958                                                 USTPUTC('\\', out);
9959                                         }
9960                                         if (SIT(c, SQSYNTAX) == CCTL)
9961                                                 USTPUTC(CTLESC, out);
9962                                         USTPUTC(c, out);
9963                                         quotef = 1;
9964                                 }
9965                                 break;
9966                         case CSQUOTE:
9967                                 syntax = SQSYNTAX;
9968  quotemark:
9969                                 if (eofmark == NULL) {
9970                                         USTPUTC(CTLQUOTEMARK, out);
9971                                 }
9972                                 break;
9973                         case CDQUOTE:
9974                                 syntax = DQSYNTAX;
9975                                 dblquote = 1;
9976                                 goto quotemark;
9977                         case CENDQUOTE:
9978                                 if (eofmark != NULL && arinest == 0
9979                                  && varnest == 0
9980                                 ) {
9981                                         USTPUTC(c, out);
9982                                 } else {
9983                                         if (dqvarnest == 0) {
9984                                                 syntax = BASESYNTAX;
9985                                                 dblquote = 0;
9986                                         }
9987                                         quotef = 1;
9988                                         goto quotemark;
9989                                 }
9990                                 break;
9991                         case CVAR:      /* '$' */
9992                                 PARSESUB();             /* parse substitution */
9993                                 break;
9994                         case CENDVAR:   /* '}' */
9995                                 if (varnest > 0) {
9996                                         varnest--;
9997                                         if (dqvarnest > 0) {
9998                                                 dqvarnest--;
9999                                         }
10000                                         USTPUTC(CTLENDVAR, out);
10001                                 } else {
10002                                         USTPUTC(c, out);
10003                                 }
10004                                 break;
10005 #if ENABLE_ASH_MATH_SUPPORT
10006                         case CLP:       /* '(' in arithmetic */
10007                                 parenlevel++;
10008                                 USTPUTC(c, out);
10009                                 break;
10010                         case CRP:       /* ')' in arithmetic */
10011                                 if (parenlevel > 0) {
10012                                         USTPUTC(c, out);
10013                                         --parenlevel;
10014                                 } else {
10015                                         if (pgetc() == ')') {
10016                                                 if (--arinest == 0) {
10017                                                         USTPUTC(CTLENDARI, out);
10018                                                         syntax = prevsyntax;
10019                                                         dblquote = (syntax == DQSYNTAX);
10020                                                 } else
10021                                                         USTPUTC(')', out);
10022                                         } else {
10023                                                 /*
10024                                                  * unbalanced parens
10025                                                  *  (don't 2nd guess - no error)
10026                                                  */
10027                                                 pungetc();
10028                                                 USTPUTC(')', out);
10029                                         }
10030                                 }
10031                                 break;
10032 #endif
10033                         case CBQUOTE:   /* '`' */
10034                                 PARSEBACKQOLD();
10035                                 break;
10036                         case CENDFILE:
10037                                 goto endword;           /* exit outer loop */
10038                         case CIGN:
10039                                 break;
10040                         default:
10041                                 if (varnest == 0)
10042                                         goto endword;   /* exit outer loop */
10043 #if ENABLE_ASH_ALIAS
10044                                 if (c != PEOA)
10045 #endif
10046                                         USTPUTC(c, out);
10047
10048                         }
10049                         c = pgetc_macro();
10050                 }
10051         }
10052  endword:
10053 #if ENABLE_ASH_MATH_SUPPORT
10054         if (syntax == ARISYNTAX)
10055                 raise_error_syntax("Missing '))'");
10056 #endif
10057         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10058                 raise_error_syntax("Unterminated quoted string");
10059         if (varnest != 0) {
10060                 startlinno = plinno;
10061                 /* { */
10062                 raise_error_syntax("Missing '}'");
10063         }
10064         USTPUTC('\0', out);
10065         len = out - (char *)stackblock();
10066         out = stackblock();
10067         if (eofmark == NULL) {
10068                 if ((c == '>' || c == '<')
10069                  && quotef == 0
10070                  && len <= 2
10071                  && (*out == '\0' || isdigit(*out))) {
10072                         PARSEREDIR();
10073                         return lasttoken = TREDIR;
10074                 } else {
10075                         pungetc();
10076                 }
10077         }
10078         quoteflag = quotef;
10079         backquotelist = bqlist;
10080         grabstackblock(len);
10081         wordtext = out;
10082         lasttoken = TWORD;
10083         return lasttoken;
10084 /* end of readtoken routine */
10085
10086 /*
10087  * Check to see whether we are at the end of the here document.  When this
10088  * is called, c is set to the first character of the next input line.  If
10089  * we are at the end of the here document, this routine sets the c to PEOF.
10090  */
10091 checkend: {
10092         if (eofmark) {
10093 #if ENABLE_ASH_ALIAS
10094                 if (c == PEOA) {
10095                         c = pgetc2();
10096                 }
10097 #endif
10098                 if (striptabs) {
10099                         while (c == '\t') {
10100                                 c = pgetc2();
10101                         }
10102                 }
10103                 if (c == *eofmark) {
10104                         if (pfgets(line, sizeof(line)) != NULL) {
10105                                 char *p, *q;
10106
10107                                 p = line;
10108                                 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10109                                 if (*p == '\n' && *q == '\0') {
10110                                         c = PEOF;
10111                                         plinno++;
10112                                         needprompt = doprompt;
10113                                 } else {
10114                                         pushstring(line, NULL);
10115                                 }
10116                         }
10117                 }
10118         }
10119         goto checkend_return;
10120 }
10121
10122 /*
10123  * Parse a redirection operator.  The variable "out" points to a string
10124  * specifying the fd to be redirected.  The variable "c" contains the
10125  * first character of the redirection operator.
10126  */
10127 parseredir: {
10128         char fd = *out;
10129         union node *np;
10130
10131         np = stalloc(sizeof(struct nfile));
10132         if (c == '>') {
10133                 np->nfile.fd = 1;
10134                 c = pgetc();
10135                 if (c == '>')
10136                         np->type = NAPPEND;
10137                 else if (c == '|')
10138                         np->type = NCLOBBER;
10139                 else if (c == '&')
10140                         np->type = NTOFD;
10141                 else {
10142                         np->type = NTO;
10143                         pungetc();
10144                 }
10145         } else {        /* c == '<' */
10146                 np->nfile.fd = 0;
10147                 c = pgetc();
10148                 switch (c) {
10149                 case '<':
10150                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10151                                 np = stalloc(sizeof(struct nhere));
10152                                 np->nfile.fd = 0;
10153                         }
10154                         np->type = NHERE;
10155                         heredoc = stalloc(sizeof(struct heredoc));
10156                         heredoc->here = np;
10157                         c = pgetc();
10158                         if (c == '-') {
10159                                 heredoc->striptabs = 1;
10160                         } else {
10161                                 heredoc->striptabs = 0;
10162                                 pungetc();
10163                         }
10164                         break;
10165
10166                 case '&':
10167                         np->type = NFROMFD;
10168                         break;
10169
10170                 case '>':
10171                         np->type = NFROMTO;
10172                         break;
10173
10174                 default:
10175                         np->type = NFROM;
10176                         pungetc();
10177                         break;
10178                 }
10179         }
10180         if (fd != '\0')
10181                 np->nfile.fd = fd - '0';
10182         redirnode = np;
10183         goto parseredir_return;
10184 }
10185
10186 /*
10187  * Parse a substitution.  At this point, we have read the dollar sign
10188  * and nothing else.
10189  */
10190
10191 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10192  * (assuming ascii char codes, as the original implementation did) */
10193 #define is_special(c) \
10194         ((((unsigned int)c) - 33 < 32) \
10195                         && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10196 parsesub: {
10197         int subtype;
10198         int typeloc;
10199         int flags;
10200         char *p;
10201         static const char types[] ALIGN1 = "}-+?=";
10202
10203         c = pgetc();
10204         if (
10205                 c <= PEOA_OR_PEOF  ||
10206                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10207         ) {
10208                 USTPUTC('$', out);
10209                 pungetc();
10210         } else if (c == '(') {  /* $(command) or $((arith)) */
10211                 if (pgetc() == '(') {
10212 #if ENABLE_ASH_MATH_SUPPORT
10213                         PARSEARITH();
10214 #else
10215                         raise_error_syntax("We unsupport $((arith))");
10216 #endif
10217                 } else {
10218                         pungetc();
10219                         PARSEBACKQNEW();
10220                 }
10221         } else {
10222                 USTPUTC(CTLVAR, out);
10223                 typeloc = out - (char *)stackblock();
10224                 USTPUTC(VSNORMAL, out);
10225                 subtype = VSNORMAL;
10226                 if (c == '{') {
10227                         c = pgetc();
10228                         if (c == '#') {
10229                                 c = pgetc();
10230                                 if (c == '}')
10231                                         c = '#';
10232                                 else
10233                                         subtype = VSLENGTH;
10234                         } else
10235                                 subtype = 0;
10236                 }
10237                 if (c > PEOA_OR_PEOF && is_name(c)) {
10238                         do {
10239                                 STPUTC(c, out);
10240                                 c = pgetc();
10241                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10242                 } else if (isdigit(c)) {
10243                         do {
10244                                 STPUTC(c, out);
10245                                 c = pgetc();
10246                         } while (isdigit(c));
10247                 } else if (is_special(c)) {
10248                         USTPUTC(c, out);
10249                         c = pgetc();
10250                 } else
10251  badsub:                raise_error_syntax("Bad substitution");
10252
10253                 STPUTC('=', out);
10254                 flags = 0;
10255                 if (subtype == 0) {
10256                         switch (c) {
10257                         case ':':
10258                                 flags = VSNUL;
10259                                 c = pgetc();
10260                                 /*FALLTHROUGH*/
10261                         default:
10262                                 p = strchr(types, c);
10263                                 if (p == NULL)
10264                                         goto badsub;
10265                                 subtype = p - types + VSNORMAL;
10266                                 break;
10267                         case '%':
10268                         case '#':
10269                                 {
10270                                         int cc = c;
10271                                         subtype = c == '#' ? VSTRIMLEFT :
10272                                                              VSTRIMRIGHT;
10273                                         c = pgetc();
10274                                         if (c == cc)
10275                                                 subtype++;
10276                                         else
10277                                                 pungetc();
10278                                         break;
10279                                 }
10280                         }
10281                 } else {
10282                         pungetc();
10283                 }
10284                 if (dblquote || arinest)
10285                         flags |= VSQUOTE;
10286                 *((char *)stackblock() + typeloc) = subtype | flags;
10287                 if (subtype != VSNORMAL) {
10288                         varnest++;
10289                         if (dblquote || arinest) {
10290                                 dqvarnest++;
10291                         }
10292                 }
10293         }
10294         goto parsesub_return;
10295 }
10296
10297 /*
10298  * Called to parse command substitutions.  Newstyle is set if the command
10299  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10300  * list of commands (passed by reference), and savelen is the number of
10301  * characters on the top of the stack which must be preserved.
10302  */
10303 parsebackq: {
10304         struct nodelist **nlpp;
10305         smallint savepbq;
10306         union node *n;
10307         char *volatile str;
10308         struct jmploc jmploc;
10309         struct jmploc *volatile savehandler;
10310         size_t savelen;
10311         smallint saveprompt = 0;
10312
10313 #ifdef __GNUC__
10314         (void) &saveprompt;
10315 #endif
10316         savepbq = parsebackquote;
10317         if (setjmp(jmploc.loc)) {
10318                 if (str)
10319                         free(str);
10320                 parsebackquote = 0;
10321                 exception_handler = savehandler;
10322                 longjmp(exception_handler->loc, 1);
10323         }
10324         INT_OFF;
10325         str = NULL;
10326         savelen = out - (char *)stackblock();
10327         if (savelen > 0) {
10328                 str = ckmalloc(savelen);
10329                 memcpy(str, stackblock(), savelen);
10330         }
10331         savehandler = exception_handler;
10332         exception_handler = &jmploc;
10333         INT_ON;
10334         if (oldstyle) {
10335                 /* We must read until the closing backquote, giving special
10336                    treatment to some slashes, and then push the string and
10337                    reread it as input, interpreting it normally.  */
10338                 char *pout;
10339                 int pc;
10340                 size_t psavelen;
10341                 char *pstr;
10342
10343
10344                 STARTSTACKSTR(pout);
10345                 for (;;) {
10346                         if (needprompt) {
10347                                 setprompt(2);
10348                         }
10349                         pc = pgetc();
10350                         switch (pc) {
10351                         case '`':
10352                                 goto done;
10353
10354                         case '\\':
10355                                 pc = pgetc();
10356                                 if (pc == '\n') {
10357                                         plinno++;
10358                                         if (doprompt)
10359                                                 setprompt(2);
10360                                         /*
10361                                          * If eating a newline, avoid putting
10362                                          * the newline into the new character
10363                                          * stream (via the STPUTC after the
10364                                          * switch).
10365                                          */
10366                                         continue;
10367                                 }
10368                                 if (pc != '\\' && pc != '`' && pc != '$'
10369                                  && (!dblquote || pc != '"'))
10370                                         STPUTC('\\', pout);
10371                                 if (pc > PEOA_OR_PEOF) {
10372                                         break;
10373                                 }
10374                                 /* fall through */
10375
10376                         case PEOF:
10377 #if ENABLE_ASH_ALIAS
10378                         case PEOA:
10379 #endif
10380                                 startlinno = plinno;
10381                                 raise_error_syntax("EOF in backquote substitution");
10382
10383                         case '\n':
10384                                 plinno++;
10385                                 needprompt = doprompt;
10386                                 break;
10387
10388                         default:
10389                                 break;
10390                         }
10391                         STPUTC(pc, pout);
10392                 }
10393  done:
10394                 STPUTC('\0', pout);
10395                 psavelen = pout - (char *)stackblock();
10396                 if (psavelen > 0) {
10397                         pstr = grabstackstr(pout);
10398                         setinputstring(pstr);
10399                 }
10400         }
10401         nlpp = &bqlist;
10402         while (*nlpp)
10403                 nlpp = &(*nlpp)->next;
10404         *nlpp = stalloc(sizeof(**nlpp));
10405         (*nlpp)->next = NULL;
10406         parsebackquote = oldstyle;
10407
10408         if (oldstyle) {
10409                 saveprompt = doprompt;
10410                 doprompt = 0;
10411         }
10412
10413         n = list(2);
10414
10415         if (oldstyle)
10416                 doprompt = saveprompt;
10417         else if (readtoken() != TRP)
10418                 raise_error_unexpected_syntax(TRP);
10419
10420         (*nlpp)->n = n;
10421         if (oldstyle) {
10422                 /*
10423                  * Start reading from old file again, ignoring any pushed back
10424                  * tokens left from the backquote parsing
10425                  */
10426                 popfile();
10427                 tokpushback = 0;
10428         }
10429         while (stackblocksize() <= savelen)
10430                 growstackblock();
10431         STARTSTACKSTR(out);
10432         if (str) {
10433                 memcpy(out, str, savelen);
10434                 STADJUST(savelen, out);
10435                 INT_OFF;
10436                 free(str);
10437                 str = NULL;
10438                 INT_ON;
10439         }
10440         parsebackquote = savepbq;
10441         exception_handler = savehandler;
10442         if (arinest || dblquote)
10443                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10444         else
10445                 USTPUTC(CTLBACKQ, out);
10446         if (oldstyle)
10447                 goto parsebackq_oldreturn;
10448         goto parsebackq_newreturn;
10449 }
10450
10451 #if ENABLE_ASH_MATH_SUPPORT
10452 /*
10453  * Parse an arithmetic expansion (indicate start of one and set state)
10454  */
10455 parsearith: {
10456         if (++arinest == 1) {
10457                 prevsyntax = syntax;
10458                 syntax = ARISYNTAX;
10459                 USTPUTC(CTLARI, out);
10460                 if (dblquote)
10461                         USTPUTC('"', out);
10462                 else
10463                         USTPUTC(' ', out);
10464         } else {
10465                 /*
10466                  * we collapse embedded arithmetic expansion to
10467                  * parenthesis, which should be equivalent
10468                  */
10469                 USTPUTC('(', out);
10470         }
10471         goto parsearith_return;
10472 }
10473 #endif
10474
10475 } /* end of readtoken */
10476
10477 /*
10478  * Read the next input token.
10479  * If the token is a word, we set backquotelist to the list of cmds in
10480  *      backquotes.  We set quoteflag to true if any part of the word was
10481  *      quoted.
10482  * If the token is TREDIR, then we set redirnode to a structure containing
10483  *      the redirection.
10484  * In all cases, the variable startlinno is set to the number of the line
10485  *      on which the token starts.
10486  *
10487  * [Change comment:  here documents and internal procedures]
10488  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10489  *  word parsing code into a separate routine.  In this case, readtoken
10490  *  doesn't need to have any internal procedures, but parseword does.
10491  *  We could also make parseoperator in essence the main routine, and
10492  *  have parseword (readtoken1?) handle both words and redirection.]
10493  */
10494 #define NEW_xxreadtoken
10495 #ifdef NEW_xxreadtoken
10496 /* singles must be first! */
10497 static const char xxreadtoken_chars[7] ALIGN1 = {
10498         '\n', '(', ')', '&', '|', ';', 0
10499 };
10500
10501 static const char xxreadtoken_tokens[] ALIGN1 = {
10502         TNL, TLP, TRP,          /* only single occurrence allowed */
10503         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10504         TEOF,                   /* corresponds to trailing nul */
10505         TAND, TOR, TENDCASE     /* if double occurrence */
10506 };
10507
10508 #define xxreadtoken_doubles \
10509         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10510 #define xxreadtoken_singles \
10511         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10512
10513 static int
10514 xxreadtoken(void)
10515 {
10516         int c;
10517
10518         if (tokpushback) {
10519                 tokpushback = 0;
10520                 return lasttoken;
10521         }
10522         if (needprompt) {
10523                 setprompt(2);
10524         }
10525         startlinno = plinno;
10526         for (;;) {                      /* until token or start of word found */
10527                 c = pgetc_macro();
10528
10529                 if ((c != ' ') && (c != '\t')
10530 #if ENABLE_ASH_ALIAS
10531                  && (c != PEOA)
10532 #endif
10533                 ) {
10534                         if (c == '#') {
10535                                 while ((c = pgetc()) != '\n' && c != PEOF);
10536                                 pungetc();
10537                         } else if (c == '\\') {
10538                                 if (pgetc() != '\n') {
10539                                         pungetc();
10540                                         goto READTOKEN1;
10541                                 }
10542                                 startlinno = ++plinno;
10543                                 if (doprompt)
10544                                         setprompt(2);
10545                         } else {
10546                                 const char *p
10547                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10548
10549                                 if (c != PEOF) {
10550                                         if (c == '\n') {
10551                                                 plinno++;
10552                                                 needprompt = doprompt;
10553                                         }
10554
10555                                         p = strchr(xxreadtoken_chars, c);
10556                                         if (p == NULL) {
10557  READTOKEN1:
10558                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10559                                         }
10560
10561                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10562                                                 if (pgetc() == *p) {    /* double occurrence? */
10563                                                         p += xxreadtoken_doubles + 1;
10564                                                 } else {
10565                                                         pungetc();
10566                                                 }
10567                                         }
10568                                 }
10569                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10570                         }
10571                 }
10572         } /* for */
10573 }
10574 #else
10575 #define RETURN(token)   return lasttoken = token
10576 static int
10577 xxreadtoken(void)
10578 {
10579         int c;
10580
10581         if (tokpushback) {
10582                 tokpushback = 0;
10583                 return lasttoken;
10584         }
10585         if (needprompt) {
10586                 setprompt(2);
10587         }
10588         startlinno = plinno;
10589         for (;;) {      /* until token or start of word found */
10590                 c = pgetc_macro();
10591                 switch (c) {
10592                 case ' ': case '\t':
10593 #if ENABLE_ASH_ALIAS
10594                 case PEOA:
10595 #endif
10596                         continue;
10597                 case '#':
10598                         while ((c = pgetc()) != '\n' && c != PEOF);
10599                         pungetc();
10600                         continue;
10601                 case '\\':
10602                         if (pgetc() == '\n') {
10603                                 startlinno = ++plinno;
10604                                 if (doprompt)
10605                                         setprompt(2);
10606                                 continue;
10607                         }
10608                         pungetc();
10609                         goto breakloop;
10610                 case '\n':
10611                         plinno++;
10612                         needprompt = doprompt;
10613                         RETURN(TNL);
10614                 case PEOF:
10615                         RETURN(TEOF);
10616                 case '&':
10617                         if (pgetc() == '&')
10618                                 RETURN(TAND);
10619                         pungetc();
10620                         RETURN(TBACKGND);
10621                 case '|':
10622                         if (pgetc() == '|')
10623                                 RETURN(TOR);
10624                         pungetc();
10625                         RETURN(TPIPE);
10626                 case ';':
10627                         if (pgetc() == ';')
10628                                 RETURN(TENDCASE);
10629                         pungetc();
10630                         RETURN(TSEMI);
10631                 case '(':
10632                         RETURN(TLP);
10633                 case ')':
10634                         RETURN(TRP);
10635                 default:
10636                         goto breakloop;
10637                 }
10638         }
10639  breakloop:
10640         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10641 #undef RETURN
10642 }
10643 #endif /* NEW_xxreadtoken */
10644
10645 static int
10646 readtoken(void)
10647 {
10648         int t;
10649 #if DEBUG
10650         smallint alreadyseen = tokpushback;
10651 #endif
10652
10653 #if ENABLE_ASH_ALIAS
10654  top:
10655 #endif
10656
10657         t = xxreadtoken();
10658
10659         /*
10660          * eat newlines
10661          */
10662         if (checkkwd & CHKNL) {
10663                 while (t == TNL) {
10664                         parseheredoc();
10665                         t = xxreadtoken();
10666                 }
10667         }
10668
10669         if (t != TWORD || quoteflag) {
10670                 goto out;
10671         }
10672
10673         /*
10674          * check for keywords
10675          */
10676         if (checkkwd & CHKKWD) {
10677                 const char *const *pp;
10678
10679                 pp = findkwd(wordtext);
10680                 if (pp) {
10681                         lasttoken = t = pp - tokname_array;
10682                         TRACE(("keyword %s recognized\n", tokname(t)));
10683                         goto out;
10684                 }
10685         }
10686
10687         if (checkkwd & CHKALIAS) {
10688 #if ENABLE_ASH_ALIAS
10689                 struct alias *ap;
10690                 ap = lookupalias(wordtext, 1);
10691                 if (ap != NULL) {
10692                         if (*ap->val) {
10693                                 pushstring(ap->val, ap);
10694                         }
10695                         goto top;
10696                 }
10697 #endif
10698         }
10699  out:
10700         checkkwd = 0;
10701 #if DEBUG
10702         if (!alreadyseen)
10703                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10704         else
10705                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10706 #endif
10707         return t;
10708 }
10709
10710 static char
10711 peektoken(void)
10712 {
10713         int t;
10714
10715         t = readtoken();
10716         tokpushback = 1;
10717         return tokname_array[t][0];
10718 }
10719
10720 /*
10721  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
10722  * valid parse tree indicating a blank line.)
10723  */
10724 static union node *
10725 parsecmd(int interact)
10726 {
10727         int t;
10728
10729         tokpushback = 0;
10730         doprompt = interact;
10731         if (doprompt)
10732                 setprompt(doprompt);
10733         needprompt = 0;
10734         t = readtoken();
10735         if (t == TEOF)
10736                 return NEOF;
10737         if (t == TNL)
10738                 return NULL;
10739         tokpushback = 1;
10740         return list(1);
10741 }
10742
10743 /*
10744  * Input any here documents.
10745  */
10746 static void
10747 parseheredoc(void)
10748 {
10749         struct heredoc *here;
10750         union node *n;
10751
10752         here = heredoclist;
10753         heredoclist = 0;
10754
10755         while (here) {
10756                 if (needprompt) {
10757                         setprompt(2);
10758                 }
10759                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10760                                 here->eofmark, here->striptabs);
10761                 n = stalloc(sizeof(struct narg));
10762                 n->narg.type = NARG;
10763                 n->narg.next = NULL;
10764                 n->narg.text = wordtext;
10765                 n->narg.backquote = backquotelist;
10766                 here->here->nhere.doc = n;
10767                 here = here->next;
10768         }
10769 }
10770
10771
10772 /*
10773  * called by editline -- any expansions to the prompt should be added here.
10774  */
10775 #if ENABLE_ASH_EXPAND_PRMT
10776 static const char *
10777 expandstr(const char *ps)
10778 {
10779         union node n;
10780
10781         /* XXX Fix (char *) cast. */
10782         setinputstring((char *)ps);
10783         readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10784         popfile();
10785
10786         n.narg.type = NARG;
10787         n.narg.next = NULL;
10788         n.narg.text = wordtext;
10789         n.narg.backquote = backquotelist;
10790
10791         expandarg(&n, NULL, 0);
10792         return stackblock();
10793 }
10794 #endif
10795
10796 /*
10797  * Execute a command or commands contained in a string.
10798  */
10799 static int
10800 evalstring(char *s, int mask)
10801 {
10802         union node *n;
10803         struct stackmark smark;
10804         int skip;
10805
10806         setinputstring(s);
10807         setstackmark(&smark);
10808
10809         skip = 0;
10810         while ((n = parsecmd(0)) != NEOF) {
10811                 evaltree(n, 0);
10812                 popstackmark(&smark);
10813                 skip = evalskip;
10814                 if (skip)
10815                         break;
10816         }
10817         popfile();
10818
10819         skip &= mask;
10820         evalskip = skip;
10821         return skip;
10822 }
10823
10824 /*
10825  * The eval command.
10826  */
10827 static int
10828 evalcmd(int argc, char **argv)
10829 {
10830         char *p;
10831         char *concat;
10832         char **ap;
10833
10834         if (argc > 1) {
10835                 p = argv[1];
10836                 if (argc > 2) {
10837                         STARTSTACKSTR(concat);
10838                         ap = argv + 2;
10839                         for (;;) {
10840                                 concat = stack_putstr(p, concat);
10841                                 p = *ap++;
10842                                 if (p == NULL)
10843                                         break;
10844                                 STPUTC(' ', concat);
10845                         }
10846                         STPUTC('\0', concat);
10847                         p = grabstackstr(concat);
10848                 }
10849                 evalstring(p, ~SKIPEVAL);
10850
10851         }
10852         return exitstatus;
10853 }
10854
10855 /*
10856  * Read and execute commands.  "Top" is nonzero for the top level command
10857  * loop; it turns on prompting if the shell is interactive.
10858  */
10859 static int
10860 cmdloop(int top)
10861 {
10862         union node *n;
10863         struct stackmark smark;
10864         int inter;
10865         int numeof = 0;
10866
10867         TRACE(("cmdloop(%d) called\n", top));
10868         for (;;) {
10869                 int skip;
10870
10871                 setstackmark(&smark);
10872 #if JOBS
10873                 if (jobctl)
10874                         showjobs(stderr, SHOW_CHANGED);
10875 #endif
10876                 inter = 0;
10877                 if (iflag && top) {
10878                         inter++;
10879 #if ENABLE_ASH_MAIL
10880                         chkmail();
10881 #endif
10882                 }
10883                 n = parsecmd(inter);
10884                 /* showtree(n); DEBUG */
10885                 if (n == NEOF) {
10886                         if (!top || numeof >= 50)
10887                                 break;
10888                         if (!stoppedjobs()) {
10889                                 if (!Iflag)
10890                                         break;
10891                                 out2str("\nUse \"exit\" to leave shell.\n");
10892                         }
10893                         numeof++;
10894                 } else if (nflag == 0) {
10895                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
10896                         job_warning >>= 1;
10897                         numeof = 0;
10898                         evaltree(n, 0);
10899                 }
10900                 popstackmark(&smark);
10901                 skip = evalskip;
10902
10903                 if (skip) {
10904                         evalskip = 0;
10905                         return skip & SKIPEVAL;
10906                 }
10907         }
10908         return 0;
10909 }
10910
10911 /*
10912  * Take commands from a file.  To be compatible we should do a path
10913  * search for the file, which is necessary to find sub-commands.
10914  */
10915 static char *
10916 find_dot_file(char *name)
10917 {
10918         char *fullname;
10919         const char *path = pathval();
10920         struct stat statb;
10921
10922         /* don't try this for absolute or relative paths */
10923         if (strchr(name, '/'))
10924                 return name;
10925
10926         while ((fullname = padvance(&path, name)) != NULL) {
10927                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
10928                         /*
10929                          * Don't bother freeing here, since it will
10930                          * be freed by the caller.
10931                          */
10932                         return fullname;
10933                 }
10934                 stunalloc(fullname);
10935         }
10936
10937         /* not found in the PATH */
10938         ash_msg_and_raise_error("%s: not found", name);
10939         /* NOTREACHED */
10940 }
10941
10942 static int
10943 dotcmd(int argc, char **argv)
10944 {
10945         struct strlist *sp;
10946         volatile struct shparam saveparam;
10947         int status = 0;
10948
10949         for (sp = cmdenviron; sp; sp = sp->next)
10950                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10951
10952         if (argc >= 2) {        /* That's what SVR2 does */
10953                 char *fullname;
10954
10955                 fullname = find_dot_file(argv[1]);
10956
10957                 if (argc > 2) {
10958                         saveparam = shellparam;
10959                         shellparam.malloc = 0;
10960                         shellparam.nparam = argc - 2;
10961                         shellparam.p = argv + 2;
10962                 };
10963
10964                 setinputfile(fullname, INPUT_PUSH_FILE);
10965                 commandname = fullname;
10966                 cmdloop(0);
10967                 popfile();
10968
10969                 if (argc > 2) {
10970                         freeparam(&shellparam);
10971                         shellparam = saveparam;
10972                 };
10973                 status = exitstatus;
10974         }
10975         return status;
10976 }
10977
10978 static int
10979 exitcmd(int argc, char **argv)
10980 {
10981         if (stoppedjobs())
10982                 return 0;
10983         if (argc > 1)
10984                 exitstatus = number(argv[1]);
10985         raise_exception(EXEXIT);
10986         /* NOTREACHED */
10987 }
10988
10989 #if ENABLE_ASH_BUILTIN_ECHO
10990 static int
10991 echocmd(int argc, char **argv)
10992 {
10993         return bb_echo(argv);
10994 }
10995 #endif
10996
10997 #if ENABLE_ASH_BUILTIN_TEST
10998 static int
10999 testcmd(int argc, char **argv)
11000 {
11001         return test_main(argc, argv);
11002 }
11003 #endif
11004
11005 /*
11006  * Read a file containing shell functions.
11007  */
11008 static void
11009 readcmdfile(char *name)
11010 {
11011         setinputfile(name, INPUT_PUSH_FILE);
11012         cmdloop(0);
11013         popfile();
11014 }
11015
11016
11017 /* ============ find_command inplementation */
11018
11019 /*
11020  * Resolve a command name.  If you change this routine, you may have to
11021  * change the shellexec routine as well.
11022  */
11023 static void
11024 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11025 {
11026         struct tblentry *cmdp;
11027         int idx;
11028         int prev;
11029         char *fullname;
11030         struct stat statb;
11031         int e;
11032         int updatetbl;
11033         struct builtincmd *bcmd;
11034
11035         /* If name contains a slash, don't use PATH or hash table */
11036         if (strchr(name, '/') != NULL) {
11037                 entry->u.index = -1;
11038                 if (act & DO_ABS) {
11039                         while (stat(name, &statb) < 0) {
11040 #ifdef SYSV
11041                                 if (errno == EINTR)
11042                                         continue;
11043 #endif
11044                                 entry->cmdtype = CMDUNKNOWN;
11045                                 return;
11046                         }
11047                 }
11048                 entry->cmdtype = CMDNORMAL;
11049                 return;
11050         }
11051
11052 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11053
11054         updatetbl = (path == pathval());
11055         if (!updatetbl) {
11056                 act |= DO_ALTPATH;
11057                 if (strstr(path, "%builtin") != NULL)
11058                         act |= DO_ALTBLTIN;
11059         }
11060
11061         /* If name is in the table, check answer will be ok */
11062         cmdp = cmdlookup(name, 0);
11063         if (cmdp != NULL) {
11064                 int bit;
11065
11066                 switch (cmdp->cmdtype) {
11067                 default:
11068 #if DEBUG
11069                         abort();
11070 #endif
11071                 case CMDNORMAL:
11072                         bit = DO_ALTPATH;
11073                         break;
11074                 case CMDFUNCTION:
11075                         bit = DO_NOFUNC;
11076                         break;
11077                 case CMDBUILTIN:
11078                         bit = DO_ALTBLTIN;
11079                         break;
11080                 }
11081                 if (act & bit) {
11082                         updatetbl = 0;
11083                         cmdp = NULL;
11084                 } else if (cmdp->rehash == 0)
11085                         /* if not invalidated by cd, we're done */
11086                         goto success;
11087         }
11088
11089         /* If %builtin not in path, check for builtin next */
11090         bcmd = find_builtin(name);
11091         if (bcmd) {
11092                 if (IS_BUILTIN_REGULAR(bcmd))
11093                         goto builtin_success;
11094                 if (act & DO_ALTPATH) {
11095                         if (!(act & DO_ALTBLTIN))
11096                                 goto builtin_success;
11097                 } else if (builtinloc <= 0) {
11098                         goto builtin_success;
11099                 }
11100         }
11101
11102 #if ENABLE_FEATURE_SH_STANDALONE
11103         if (find_applet_by_name(name)) {
11104                 entry->cmdtype = CMDNORMAL;
11105                 entry->u.index = -1;
11106                 return;
11107         }
11108 #endif
11109
11110         /* We have to search path. */
11111         prev = -1;              /* where to start */
11112         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11113                 if (cmdp->cmdtype == CMDBUILTIN)
11114                         prev = builtinloc;
11115                 else
11116                         prev = cmdp->param.index;
11117         }
11118
11119         e = ENOENT;
11120         idx = -1;
11121  loop:
11122         while ((fullname = padvance(&path, name)) != NULL) {
11123                 stunalloc(fullname);
11124                 /* NB: code below will still use fullname
11125                  * despite it being "unallocated" */
11126                 idx++;
11127                 if (pathopt) {
11128                         if (prefix(pathopt, "builtin")) {
11129                                 if (bcmd)
11130                                         goto builtin_success;
11131                                 continue;
11132                         } else if (!(act & DO_NOFUNC)
11133                          && prefix(pathopt, "func")) {
11134                                 /* handled below */
11135                         } else {
11136                                 /* ignore unimplemented options */
11137                                 continue;
11138                         }
11139                 }
11140                 /* if rehash, don't redo absolute path names */
11141                 if (fullname[0] == '/' && idx <= prev) {
11142                         if (idx < prev)
11143                                 continue;
11144                         TRACE(("searchexec \"%s\": no change\n", name));
11145                         goto success;
11146                 }
11147                 while (stat(fullname, &statb) < 0) {
11148 #ifdef SYSV
11149                         if (errno == EINTR)
11150                                 continue;
11151 #endif
11152                         if (errno != ENOENT && errno != ENOTDIR)
11153                                 e = errno;
11154                         goto loop;
11155                 }
11156                 e = EACCES;     /* if we fail, this will be the error */
11157                 if (!S_ISREG(statb.st_mode))
11158                         continue;
11159                 if (pathopt) {          /* this is a %func directory */
11160                         stalloc(strlen(fullname) + 1);
11161                         /* NB: stalloc will return space pointed by fullname
11162                          * (because we don't have any intervening allocations
11163                          * between stunalloc above and this stalloc) */
11164                         readcmdfile(fullname);
11165                         cmdp = cmdlookup(name, 0);
11166                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11167                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11168                         stunalloc(fullname);
11169                         goto success;
11170                 }
11171                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11172                 if (!updatetbl) {
11173                         entry->cmdtype = CMDNORMAL;
11174                         entry->u.index = idx;
11175                         return;
11176                 }
11177                 INT_OFF;
11178                 cmdp = cmdlookup(name, 1);
11179                 cmdp->cmdtype = CMDNORMAL;
11180                 cmdp->param.index = idx;
11181                 INT_ON;
11182                 goto success;
11183         }
11184
11185         /* We failed.  If there was an entry for this command, delete it */
11186         if (cmdp && updatetbl)
11187                 delete_cmd_entry();
11188         if (act & DO_ERR)
11189                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11190         entry->cmdtype = CMDUNKNOWN;
11191         return;
11192
11193  builtin_success:
11194         if (!updatetbl) {
11195                 entry->cmdtype = CMDBUILTIN;
11196                 entry->u.cmd = bcmd;
11197                 return;
11198         }
11199         INT_OFF;
11200         cmdp = cmdlookup(name, 1);
11201         cmdp->cmdtype = CMDBUILTIN;
11202         cmdp->param.cmd = bcmd;
11203         INT_ON;
11204  success:
11205         cmdp->rehash = 0;
11206         entry->cmdtype = cmdp->cmdtype;
11207         entry->u = cmdp->param;
11208 }
11209
11210
11211 /* ============ trap.c */
11212
11213 /*
11214  * The trap builtin.
11215  */
11216 static int
11217 trapcmd(int argc, char **argv)
11218 {
11219         char *action;
11220         char **ap;
11221         int signo;
11222
11223         nextopt(nullstr);
11224         ap = argptr;
11225         if (!*ap) {
11226                 for (signo = 0; signo < NSIG; signo++) {
11227                         if (trap[signo] != NULL) {
11228                                 const char *sn;
11229
11230                                 sn = get_signame(signo);
11231                                 out1fmt("trap -- %s %s\n",
11232                                         single_quote(trap[signo]), sn);
11233                         }
11234                 }
11235                 return 0;
11236         }
11237         if (!ap[1])
11238                 action = NULL;
11239         else
11240                 action = *ap++;
11241         while (*ap) {
11242                 signo = get_signum(*ap);
11243                 if (signo < 0)
11244                         ash_msg_and_raise_error("%s: bad trap", *ap);
11245                 INT_OFF;
11246                 if (action) {
11247                         if (LONE_DASH(action))
11248                                 action = NULL;
11249                         else
11250                                 action = ckstrdup(action);
11251                 }
11252                 if (trap[signo])
11253                         free(trap[signo]);
11254                 trap[signo] = action;
11255                 if (signo != 0)
11256                         setsignal(signo);
11257                 INT_ON;
11258                 ap++;
11259         }
11260         return 0;
11261 }
11262
11263
11264 /* ============ Builtins */
11265
11266 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11267 /*
11268  * Lists available builtins
11269  */
11270 static int
11271 helpcmd(int argc, char **argv)
11272 {
11273         int col, i;
11274
11275         out1fmt("\nBuilt-in commands:\n-------------------\n");
11276         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11277                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11278                                         builtintab[i].name + 1);
11279                 if (col > 60) {
11280                         out1fmt("\n");
11281                         col = 0;
11282                 }
11283         }
11284 #if ENABLE_FEATURE_SH_STANDALONE
11285         for (i = 0; i < NUM_APPLETS; i++) {
11286                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11287                 if (col > 60) {
11288                         out1fmt("\n");
11289                         col = 0;
11290                 }
11291         }
11292 #endif
11293         out1fmt("\n\n");
11294         return EXIT_SUCCESS;
11295 }
11296 #endif /* FEATURE_SH_EXTRA_QUIET */
11297
11298 /*
11299  * The export and readonly commands.
11300  */
11301 static int
11302 exportcmd(int argc, char **argv)
11303 {
11304         struct var *vp;
11305         char *name;
11306         const char *p;
11307         char **aptr;
11308         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11309
11310         if (nextopt("p") != 'p') {
11311                 aptr = argptr;
11312                 name = *aptr;
11313                 if (name) {
11314                         do {
11315                                 p = strchr(name, '=');
11316                                 if (p != NULL) {
11317                                         p++;
11318                                 } else {
11319                                         vp = *findvar(hashvar(name), name);
11320                                         if (vp) {
11321                                                 vp->flags |= flag;
11322                                                 continue;
11323                                         }
11324                                 }
11325                                 setvar(name, p, flag);
11326                         } while ((name = *++aptr) != NULL);
11327                         return 0;
11328                 }
11329         }
11330         showvars(argv[0], flag, 0);
11331         return 0;
11332 }
11333
11334 /*
11335  * Delete a function if it exists.
11336  */
11337 static void
11338 unsetfunc(const char *name)
11339 {
11340         struct tblentry *cmdp;
11341
11342         cmdp = cmdlookup(name, 0);
11343         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11344                 delete_cmd_entry();
11345 }
11346
11347 /*
11348  * The unset builtin command.  We unset the function before we unset the
11349  * variable to allow a function to be unset when there is a readonly variable
11350  * with the same name.
11351  */
11352 static int
11353 unsetcmd(int argc, char **argv)
11354 {
11355         char **ap;
11356         int i;
11357         int flag = 0;
11358         int ret = 0;
11359
11360         while ((i = nextopt("vf")) != '\0') {
11361                 flag = i;
11362         }
11363
11364         for (ap = argptr; *ap; ap++) {
11365                 if (flag != 'f') {
11366                         i = unsetvar(*ap);
11367                         ret |= i;
11368                         if (!(i & 2))
11369                                 continue;
11370                 }
11371                 if (flag != 'v')
11372                         unsetfunc(*ap);
11373         }
11374         return ret & 1;
11375 }
11376
11377
11378 /*      setmode.c      */
11379
11380 #include <sys/times.h>
11381
11382 static const unsigned char timescmd_str[] ALIGN1 = {
11383         ' ',  offsetof(struct tms, tms_utime),
11384         '\n', offsetof(struct tms, tms_stime),
11385         ' ',  offsetof(struct tms, tms_cutime),
11386         '\n', offsetof(struct tms, tms_cstime),
11387         0
11388 };
11389
11390 static int
11391 timescmd(int ac, char **av)
11392 {
11393         long clk_tck, s, t;
11394         const unsigned char *p;
11395         struct tms buf;
11396
11397         clk_tck = sysconf(_SC_CLK_TCK);
11398         times(&buf);
11399
11400         p = timescmd_str;
11401         do {
11402                 t = *(clock_t *)(((char *) &buf) + p[1]);
11403                 s = t / clk_tck;
11404                 out1fmt("%ldm%ld.%.3lds%c",
11405                         s/60, s%60,
11406                         ((t - s * clk_tck) * 1000) / clk_tck,
11407                         p[0]);
11408         } while (*(p += 2));
11409
11410         return 0;
11411 }
11412
11413 #if ENABLE_ASH_MATH_SUPPORT
11414 static arith_t
11415 dash_arith(const char *s)
11416 {
11417         arith_t result;
11418         int errcode = 0;
11419
11420         INT_OFF;
11421         result = arith(s, &errcode);
11422         if (errcode < 0) {
11423                 if (errcode == -3)
11424                         ash_msg_and_raise_error("exponent less than 0");
11425                 if (errcode == -2)
11426                         ash_msg_and_raise_error("divide by zero");
11427                 if (errcode == -5)
11428                         ash_msg_and_raise_error("expression recursion loop detected");
11429                 raise_error_syntax(s);
11430         }
11431         INT_ON;
11432
11433         return result;
11434 }
11435
11436 /*
11437  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11438  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11439  *
11440  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11441  */
11442 static int
11443 letcmd(int argc, char **argv)
11444 {
11445         char **ap;
11446         arith_t i = 0;
11447
11448         ap = argv + 1;
11449         if (!*ap)
11450                 ash_msg_and_raise_error("expression expected");
11451         for (ap = argv + 1; *ap; ap++) {
11452                 i = dash_arith(*ap);
11453         }
11454
11455         return !i;
11456 }
11457 #endif /* ASH_MATH_SUPPORT */
11458
11459
11460 /* ============ miscbltin.c
11461  *
11462  * Miscellaneous builtins.
11463  */
11464
11465 #undef rflag
11466
11467 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11468 typedef enum __rlimit_resource rlim_t;
11469 #endif
11470
11471 /*
11472  * The read builtin.  The -e option causes backslashes to escape the
11473  * following character.
11474  *
11475  * This uses unbuffered input, which may be avoidable in some cases.
11476  */
11477 static int
11478 readcmd(int argc, char **argv)
11479 {
11480         char **ap;
11481         int backslash;
11482         char c;
11483         int rflag;
11484         char *prompt;
11485         const char *ifs;
11486         char *p;
11487         int startword;
11488         int status;
11489         int i;
11490 #if ENABLE_ASH_READ_NCHARS
11491         int nch_flag = 0;
11492         int nchars = 0;
11493         int silent = 0;
11494         struct termios tty, old_tty;
11495 #endif
11496 #if ENABLE_ASH_READ_TIMEOUT
11497         fd_set set;
11498         struct timeval ts;
11499
11500         ts.tv_sec = ts.tv_usec = 0;
11501 #endif
11502
11503         rflag = 0;
11504         prompt = NULL;
11505 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11506         while ((i = nextopt("p:rt:n:s")) != '\0')
11507 #elif ENABLE_ASH_READ_NCHARS
11508         while ((i = nextopt("p:rn:s")) != '\0')
11509 #elif ENABLE_ASH_READ_TIMEOUT
11510         while ((i = nextopt("p:rt:")) != '\0')
11511 #else
11512         while ((i = nextopt("p:r")) != '\0')
11513 #endif
11514         {
11515                 switch (i) {
11516                 case 'p':
11517                         prompt = optionarg;
11518                         break;
11519 #if ENABLE_ASH_READ_NCHARS
11520                 case 'n':
11521                         nchars = strtol(optionarg, &p, 10);
11522                         if (*p)
11523                                 ash_msg_and_raise_error("invalid count");
11524                         nch_flag = (nchars > 0);
11525                         break;
11526                 case 's':
11527                         silent = 1;
11528                         break;
11529 #endif
11530 #if ENABLE_ASH_READ_TIMEOUT
11531                 case 't':
11532                         ts.tv_sec = strtol(optionarg, &p, 10);
11533                         ts.tv_usec = 0;
11534                         if (*p == '.') {
11535                                 char *p2;
11536                                 if (*++p) {
11537                                         int scale;
11538                                         ts.tv_usec = strtol(p, &p2, 10);
11539                                         if (*p2)
11540                                                 ash_msg_and_raise_error("invalid timeout");
11541                                         scale = p2 - p;
11542                                         /* normalize to usec */
11543                                         if (scale > 6)
11544                                                 ash_msg_and_raise_error("invalid timeout");
11545                                         while (scale++ < 6)
11546                                                 ts.tv_usec *= 10;
11547                                 }
11548                         } else if (*p) {
11549                                 ash_msg_and_raise_error("invalid timeout");
11550                         }
11551                         if ( ! ts.tv_sec && ! ts.tv_usec)
11552                                 ash_msg_and_raise_error("invalid timeout");
11553                         break;
11554 #endif
11555                 case 'r':
11556                         rflag = 1;
11557                         break;
11558                 default:
11559                         break;
11560                 }
11561         }
11562         if (prompt && isatty(0)) {
11563                 out2str(prompt);
11564         }
11565         ap = argptr;
11566         if (*ap == NULL)
11567                 ash_msg_and_raise_error("arg count");
11568         ifs = bltinlookup("IFS");
11569         if (ifs == NULL)
11570                 ifs = defifs;
11571 #if ENABLE_ASH_READ_NCHARS
11572         if (nch_flag || silent) {
11573                 tcgetattr(0, &tty);
11574                 old_tty = tty;
11575                 if (nch_flag) {
11576                         tty.c_lflag &= ~ICANON;
11577                         tty.c_cc[VMIN] = nchars;
11578                 }
11579                 if (silent) {
11580                         tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11581
11582                 }
11583                 tcsetattr(0, TCSANOW, &tty);
11584         }
11585 #endif
11586 #if ENABLE_ASH_READ_TIMEOUT
11587         if (ts.tv_sec || ts.tv_usec) {
11588 // TODO: replace with poll, it is smaller
11589                 FD_ZERO(&set);
11590                 FD_SET(0, &set);
11591
11592                 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11593                 if (!i) {
11594 #if ENABLE_ASH_READ_NCHARS
11595                         if (nch_flag)
11596                                 tcsetattr(0, TCSANOW, &old_tty);
11597 #endif
11598                         return 1;
11599                 }
11600         }
11601 #endif
11602         status = 0;
11603         startword = 1;
11604         backslash = 0;
11605         STARTSTACKSTR(p);
11606 #if ENABLE_ASH_READ_NCHARS
11607         while (!nch_flag || nchars--)
11608 #else
11609         for (;;)
11610 #endif
11611         {
11612                 if (read(0, &c, 1) != 1) {
11613                         status = 1;
11614                         break;
11615                 }
11616                 if (c == '\0')
11617                         continue;
11618                 if (backslash) {
11619                         backslash = 0;
11620                         if (c != '\n')
11621                                 goto put;
11622                         continue;
11623                 }
11624                 if (!rflag && c == '\\') {
11625                         backslash++;
11626                         continue;
11627                 }
11628                 if (c == '\n')
11629                         break;
11630                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11631                         continue;
11632                 }
11633                 startword = 0;
11634                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11635                         STACKSTRNUL(p);
11636                         setvar(*ap, stackblock(), 0);
11637                         ap++;
11638                         startword = 1;
11639                         STARTSTACKSTR(p);
11640                 } else {
11641  put:
11642                         STPUTC(c, p);
11643                 }
11644         }
11645 #if ENABLE_ASH_READ_NCHARS
11646         if (nch_flag || silent)
11647                 tcsetattr(0, TCSANOW, &old_tty);
11648 #endif
11649
11650         STACKSTRNUL(p);
11651         /* Remove trailing blanks */
11652         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11653                 *p = '\0';
11654         setvar(*ap, stackblock(), 0);
11655         while (*++ap != NULL)
11656                 setvar(*ap, nullstr, 0);
11657         return status;
11658 }
11659
11660 static int
11661 umaskcmd(int argc, char **argv)
11662 {
11663         static const char permuser[3] ALIGN1 = "ugo";
11664         static const char permmode[3] ALIGN1 = "rwx";
11665         static const short permmask[] ALIGN2 = {
11666                 S_IRUSR, S_IWUSR, S_IXUSR,
11667                 S_IRGRP, S_IWGRP, S_IXGRP,
11668                 S_IROTH, S_IWOTH, S_IXOTH
11669         };
11670
11671         char *ap;
11672         mode_t mask;
11673         int i;
11674         int symbolic_mode = 0;
11675
11676         while (nextopt("S") != '\0') {
11677                 symbolic_mode = 1;
11678         }
11679
11680         INT_OFF;
11681         mask = umask(0);
11682         umask(mask);
11683         INT_ON;
11684
11685         ap = *argptr;
11686         if (ap == NULL) {
11687                 if (symbolic_mode) {
11688                         char buf[18];
11689                         char *p = buf;
11690
11691                         for (i = 0; i < 3; i++) {
11692                                 int j;
11693
11694                                 *p++ = permuser[i];
11695                                 *p++ = '=';
11696                                 for (j = 0; j < 3; j++) {
11697                                         if ((mask & permmask[3 * i + j]) == 0) {
11698                                                 *p++ = permmode[j];
11699                                         }
11700                                 }
11701                                 *p++ = ',';
11702                         }
11703                         *--p = 0;
11704                         puts(buf);
11705                 } else {
11706                         out1fmt("%.4o\n", mask);
11707                 }
11708         } else {
11709                 if (isdigit((unsigned char) *ap)) {
11710                         mask = 0;
11711                         do {
11712                                 if (*ap >= '8' || *ap < '0')
11713                                         ash_msg_and_raise_error(illnum, argv[1]);
11714                                 mask = (mask << 3) + (*ap - '0');
11715                         } while (*++ap != '\0');
11716                         umask(mask);
11717                 } else {
11718                         mask = ~mask & 0777;
11719                         if (!bb_parse_mode(ap, &mask)) {
11720                                 ash_msg_and_raise_error("illegal mode: %s", ap);
11721                         }
11722                         umask(~mask & 0777);
11723                 }
11724         }
11725         return 0;
11726 }
11727
11728 /*
11729  * ulimit builtin
11730  *
11731  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11732  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11733  * ash by J.T. Conklin.
11734  *
11735  * Public domain.
11736  */
11737
11738 struct limits {
11739         const char *name;
11740         int     cmd;
11741         int     factor; /* multiply by to get rlim_{cur,max} values */
11742         char    option;
11743 };
11744
11745 static const struct limits limits[] = {
11746 #ifdef RLIMIT_CPU
11747         { "time(seconds)",              RLIMIT_CPU,        1, 't' },
11748 #endif
11749 #ifdef RLIMIT_FSIZE
11750         { "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
11751 #endif
11752 #ifdef RLIMIT_DATA
11753         { "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
11754 #endif
11755 #ifdef RLIMIT_STACK
11756         { "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
11757 #endif
11758 #ifdef  RLIMIT_CORE
11759         { "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
11760 #endif
11761 #ifdef RLIMIT_RSS
11762         { "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
11763 #endif
11764 #ifdef RLIMIT_MEMLOCK
11765         { "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
11766 #endif
11767 #ifdef RLIMIT_NPROC
11768         { "process",                    RLIMIT_NPROC,      1, 'p' },
11769 #endif
11770 #ifdef RLIMIT_NOFILE
11771         { "nofiles",                    RLIMIT_NOFILE,     1, 'n' },
11772 #endif
11773 #ifdef RLIMIT_AS
11774         { "vmemory(kbytes)",            RLIMIT_AS,      1024, 'v' },
11775 #endif
11776 #ifdef RLIMIT_LOCKS
11777         { "locks",                      RLIMIT_LOCKS,      1, 'w' },
11778 #endif
11779         { NULL,                         0,                 0,  '\0' }
11780 };
11781
11782 enum limtype { SOFT = 0x1, HARD = 0x2 };
11783
11784 static void
11785 printlim(enum limtype how, const struct rlimit *limit,
11786                         const struct limits *l)
11787 {
11788         rlim_t val;
11789
11790         val = limit->rlim_max;
11791         if (how & SOFT)
11792                 val = limit->rlim_cur;
11793
11794         if (val == RLIM_INFINITY)
11795                 out1fmt("unlimited\n");
11796         else {
11797                 val /= l->factor;
11798                 out1fmt("%lld\n", (long long) val);
11799         }
11800 }
11801
11802 static int
11803 ulimitcmd(int argc, char **argv)
11804 {
11805         int c;
11806         rlim_t val = 0;
11807         enum limtype how = SOFT | HARD;
11808         const struct limits *l;
11809         int set, all = 0;
11810         int optc, what;
11811         struct rlimit limit;
11812
11813         what = 'f';
11814         while ((optc = nextopt("HSa"
11815 #ifdef RLIMIT_CPU
11816                                 "t"
11817 #endif
11818 #ifdef RLIMIT_FSIZE
11819                                 "f"
11820 #endif
11821 #ifdef RLIMIT_DATA
11822                                 "d"
11823 #endif
11824 #ifdef RLIMIT_STACK
11825                                 "s"
11826 #endif
11827 #ifdef RLIMIT_CORE
11828                                 "c"
11829 #endif
11830 #ifdef RLIMIT_RSS
11831                                 "m"
11832 #endif
11833 #ifdef RLIMIT_MEMLOCK
11834                                 "l"
11835 #endif
11836 #ifdef RLIMIT_NPROC
11837                                 "p"
11838 #endif
11839 #ifdef RLIMIT_NOFILE
11840                                 "n"
11841 #endif
11842 #ifdef RLIMIT_AS
11843                                 "v"
11844 #endif
11845 #ifdef RLIMIT_LOCKS
11846                                 "w"
11847 #endif
11848                                         )) != '\0')
11849                 switch (optc) {
11850                 case 'H':
11851                         how = HARD;
11852                         break;
11853                 case 'S':
11854                         how = SOFT;
11855                         break;
11856                 case 'a':
11857                         all = 1;
11858                         break;
11859                 default:
11860                         what = optc;
11861                 }
11862
11863         for (l = limits; l->option != what; l++)
11864                 ;
11865
11866         set = *argptr ? 1 : 0;
11867         if (set) {
11868                 char *p = *argptr;
11869
11870                 if (all || argptr[1])
11871                         ash_msg_and_raise_error("too many arguments");
11872                 if (strncmp(p, "unlimited\n", 9) == 0)
11873                         val = RLIM_INFINITY;
11874                 else {
11875                         val = (rlim_t) 0;
11876
11877                         while ((c = *p++) >= '0' && c <= '9') {
11878                                 val = (val * 10) + (long)(c - '0');
11879                                 if (val < (rlim_t) 0)
11880                                         break;
11881                         }
11882                         if (c)
11883                                 ash_msg_and_raise_error("bad number");
11884                         val *= l->factor;
11885                 }
11886         }
11887         if (all) {
11888                 for (l = limits; l->name; l++) {
11889                         getrlimit(l->cmd, &limit);
11890                         out1fmt("%-20s ", l->name);
11891                         printlim(how, &limit, l);
11892                 }
11893                 return 0;
11894         }
11895
11896         getrlimit(l->cmd, &limit);
11897         if (set) {
11898                 if (how & HARD)
11899                         limit.rlim_max = val;
11900                 if (how & SOFT)
11901                         limit.rlim_cur = val;
11902                 if (setrlimit(l->cmd, &limit) < 0)
11903                         ash_msg_and_raise_error("error setting limit (%m)");
11904         } else {
11905                 printlim(how, &limit, l);
11906         }
11907         return 0;
11908 }
11909
11910
11911 /* ============ Math support */
11912
11913 #if ENABLE_ASH_MATH_SUPPORT
11914
11915 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
11916
11917    Permission is hereby granted, free of charge, to any person obtaining
11918    a copy of this software and associated documentation files (the
11919    "Software"), to deal in the Software without restriction, including
11920    without limitation the rights to use, copy, modify, merge, publish,
11921    distribute, sublicense, and/or sell copies of the Software, and to
11922    permit persons to whom the Software is furnished to do so, subject to
11923    the following conditions:
11924
11925    The above copyright notice and this permission notice shall be
11926    included in all copies or substantial portions of the Software.
11927
11928    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11929    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11930    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11931    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
11932    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11933    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11934    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11935 */
11936
11937 /* This is my infix parser/evaluator. It is optimized for size, intended
11938  * as a replacement for yacc-based parsers. However, it may well be faster
11939  * than a comparable parser written in yacc. The supported operators are
11940  * listed in #defines below. Parens, order of operations, and error handling
11941  * are supported. This code is thread safe. The exact expression format should
11942  * be that which POSIX specifies for shells. */
11943
11944 /* The code uses a simple two-stack algorithm. See
11945  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
11946  * for a detailed explanation of the infix-to-postfix algorithm on which
11947  * this is based (this code differs in that it applies operators immediately
11948  * to the stack instead of adding them to a queue to end up with an
11949  * expression). */
11950
11951 /* To use the routine, call it with an expression string and error return
11952  * pointer */
11953
11954 /*
11955  * Aug 24, 2001              Manuel Novoa III
11956  *
11957  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
11958  *
11959  * 1) In arith_apply():
11960  *    a) Cached values of *numptr and &(numptr[-1]).
11961  *    b) Removed redundant test for zero denominator.
11962  *
11963  * 2) In arith():
11964  *    a) Eliminated redundant code for processing operator tokens by moving
11965  *       to a table-based implementation.  Also folded handling of parens
11966  *       into the table.
11967  *    b) Combined all 3 loops which called arith_apply to reduce generated
11968  *       code size at the cost of speed.
11969  *
11970  * 3) The following expressions were treated as valid by the original code:
11971  *       1()  ,    0!  ,    1 ( *3 )   .
11972  *    These bugs have been fixed by internally enclosing the expression in
11973  *    parens and then checking that all binary ops and right parens are
11974  *    preceded by a valid expression (NUM_TOKEN).
11975  *
11976  * Note: It may be desirable to replace Aaron's test for whitespace with
11977  * ctype's isspace() if it is used by another busybox applet or if additional
11978  * whitespace chars should be considered.  Look below the "#include"s for a
11979  * precompiler test.
11980  */
11981
11982 /*
11983  * Aug 26, 2001              Manuel Novoa III
11984  *
11985  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
11986  *
11987  * Merge in Aaron's comments previously posted to the busybox list,
11988  * modified slightly to take account of my changes to the code.
11989  *
11990  */
11991
11992 /*
11993  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11994  *
11995  * - allow access to variable,
11996  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
11997  * - realize assign syntax (VAR=expr, +=, *= etc)
11998  * - realize exponentiation (** operator)
11999  * - realize comma separated - expr, expr
12000  * - realise ++expr --expr expr++ expr--
12001  * - realise expr ? expr : expr (but, second expr calculate always)
12002  * - allow hexadecimal and octal numbers
12003  * - was restored loses XOR operator
12004  * - remove one goto label, added three ;-)
12005  * - protect $((num num)) as true zero expr (Manuel`s error)
12006  * - always use special isspace(), see comment from bash ;-)
12007  */
12008
12009 #define arith_isspace(arithval) \
12010         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12011
12012 typedef unsigned char operator;
12013
12014 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12015  * precedence, and 3 high bits are an ID unique across operators of that
12016  * precedence. The ID portion is so that multiple operators can have the
12017  * same precedence, ensuring that the leftmost one is evaluated first.
12018  * Consider * and /. */
12019
12020 #define tok_decl(prec,id) (((id)<<5)|(prec))
12021 #define PREC(op) ((op) & 0x1F)
12022
12023 #define TOK_LPAREN tok_decl(0,0)
12024
12025 #define TOK_COMMA tok_decl(1,0)
12026
12027 #define TOK_ASSIGN tok_decl(2,0)
12028 #define TOK_AND_ASSIGN tok_decl(2,1)
12029 #define TOK_OR_ASSIGN tok_decl(2,2)
12030 #define TOK_XOR_ASSIGN tok_decl(2,3)
12031 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12032 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12033 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12034 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12035
12036 #define TOK_MUL_ASSIGN tok_decl(3,0)
12037 #define TOK_DIV_ASSIGN tok_decl(3,1)
12038 #define TOK_REM_ASSIGN tok_decl(3,2)
12039
12040 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12041 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12042
12043 /* conditional is right associativity too */
12044 #define TOK_CONDITIONAL tok_decl(4,0)
12045 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12046
12047 #define TOK_OR tok_decl(5,0)
12048
12049 #define TOK_AND tok_decl(6,0)
12050
12051 #define TOK_BOR tok_decl(7,0)
12052
12053 #define TOK_BXOR tok_decl(8,0)
12054
12055 #define TOK_BAND tok_decl(9,0)
12056
12057 #define TOK_EQ tok_decl(10,0)
12058 #define TOK_NE tok_decl(10,1)
12059
12060 #define TOK_LT tok_decl(11,0)
12061 #define TOK_GT tok_decl(11,1)
12062 #define TOK_GE tok_decl(11,2)
12063 #define TOK_LE tok_decl(11,3)
12064
12065 #define TOK_LSHIFT tok_decl(12,0)
12066 #define TOK_RSHIFT tok_decl(12,1)
12067
12068 #define TOK_ADD tok_decl(13,0)
12069 #define TOK_SUB tok_decl(13,1)
12070
12071 #define TOK_MUL tok_decl(14,0)
12072 #define TOK_DIV tok_decl(14,1)
12073 #define TOK_REM tok_decl(14,2)
12074
12075 /* exponent is right associativity */
12076 #define TOK_EXPONENT tok_decl(15,1)
12077
12078 /* For now unary operators. */
12079 #define UNARYPREC 16
12080 #define TOK_BNOT tok_decl(UNARYPREC,0)
12081 #define TOK_NOT tok_decl(UNARYPREC,1)
12082
12083 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12084 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12085
12086 #define PREC_PRE (UNARYPREC+2)
12087
12088 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12089 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12090
12091 #define PREC_POST (UNARYPREC+3)
12092
12093 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12094 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12095
12096 #define SPEC_PREC (UNARYPREC+4)
12097
12098 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12099 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12100
12101 #define NUMPTR (*numstackptr)
12102
12103 static int
12104 tok_have_assign(operator op)
12105 {
12106         operator prec = PREC(op);
12107
12108         convert_prec_is_assing(prec);
12109         return (prec == PREC(TOK_ASSIGN) ||
12110                         prec == PREC_PRE || prec == PREC_POST);
12111 }
12112
12113 static int
12114 is_right_associativity(operator prec)
12115 {
12116         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12117                 || prec == PREC(TOK_CONDITIONAL));
12118 }
12119
12120 typedef struct ARITCH_VAR_NUM {
12121         arith_t val;
12122         arith_t contidional_second_val;
12123         char contidional_second_val_initialized;
12124         char *var;      /* if NULL then is regular number,
12125                            else is variable name */
12126 } v_n_t;
12127
12128 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12129         const char *var;
12130         struct CHK_VAR_RECURSIVE_LOOPED *next;
12131 } chk_var_recursive_looped_t;
12132
12133 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12134
12135 static int
12136 arith_lookup_val(v_n_t *t)
12137 {
12138         if (t->var) {
12139                 const char * p = lookupvar(t->var);
12140
12141                 if (p) {
12142                         int errcode;
12143
12144                         /* recursive try as expression */
12145                         chk_var_recursive_looped_t *cur;
12146                         chk_var_recursive_looped_t cur_save;
12147
12148                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12149                                 if (strcmp(cur->var, t->var) == 0) {
12150                                         /* expression recursion loop detected */
12151                                         return -5;
12152                                 }
12153                         }
12154                         /* save current lookuped var name */
12155                         cur = prev_chk_var_recursive;
12156                         cur_save.var = t->var;
12157                         cur_save.next = cur;
12158                         prev_chk_var_recursive = &cur_save;
12159
12160                         t->val = arith (p, &errcode);
12161                         /* restore previous ptr after recursiving */
12162                         prev_chk_var_recursive = cur;
12163                         return errcode;
12164                 }
12165                 /* allow undefined var as 0 */
12166                 t->val = 0;
12167         }
12168         return 0;
12169 }
12170
12171 /* "applying" a token means performing it on the top elements on the integer
12172  * stack. For a unary operator it will only change the top element, but a
12173  * binary operator will pop two arguments and push a result */
12174 static int
12175 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12176 {
12177         v_n_t *numptr_m1;
12178         arith_t numptr_val, rez;
12179         int ret_arith_lookup_val;
12180
12181         /* There is no operator that can work without arguments */
12182         if (NUMPTR == numstack) goto err;
12183         numptr_m1 = NUMPTR - 1;
12184
12185         /* check operand is var with noninteger value */
12186         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12187         if (ret_arith_lookup_val)
12188                 return ret_arith_lookup_val;
12189
12190         rez = numptr_m1->val;
12191         if (op == TOK_UMINUS)
12192                 rez *= -1;
12193         else if (op == TOK_NOT)
12194                 rez = !rez;
12195         else if (op == TOK_BNOT)
12196                 rez = ~rez;
12197         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12198                 rez++;
12199         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12200                 rez--;
12201         else if (op != TOK_UPLUS) {
12202                 /* Binary operators */
12203
12204                 /* check and binary operators need two arguments */
12205                 if (numptr_m1 == numstack) goto err;
12206
12207                 /* ... and they pop one */
12208                 --NUMPTR;
12209                 numptr_val = rez;
12210                 if (op == TOK_CONDITIONAL) {
12211                         if (! numptr_m1->contidional_second_val_initialized) {
12212                                 /* protect $((expr1 ? expr2)) without ": expr" */
12213                                 goto err;
12214                         }
12215                         rez = numptr_m1->contidional_second_val;
12216                 } else if (numptr_m1->contidional_second_val_initialized) {
12217                         /* protect $((expr1 : expr2)) without "expr ? " */
12218                         goto err;
12219                 }
12220                 numptr_m1 = NUMPTR - 1;
12221                 if (op != TOK_ASSIGN) {
12222                         /* check operand is var with noninteger value for not '=' */
12223                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12224                         if (ret_arith_lookup_val)
12225                                 return ret_arith_lookup_val;
12226                 }
12227                 if (op == TOK_CONDITIONAL) {
12228                         numptr_m1->contidional_second_val = rez;
12229                 }
12230                 rez = numptr_m1->val;
12231                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12232                         rez |= numptr_val;
12233                 else if (op == TOK_OR)
12234                         rez = numptr_val || rez;
12235                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12236                         rez &= numptr_val;
12237                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12238                         rez ^= numptr_val;
12239                 else if (op == TOK_AND)
12240                         rez = rez && numptr_val;
12241                 else if (op == TOK_EQ)
12242                         rez = (rez == numptr_val);
12243                 else if (op == TOK_NE)
12244                         rez = (rez != numptr_val);
12245                 else if (op == TOK_GE)
12246                         rez = (rez >= numptr_val);
12247                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12248                         rez >>= numptr_val;
12249                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12250                         rez <<= numptr_val;
12251                 else if (op == TOK_GT)
12252                         rez = (rez > numptr_val);
12253                 else if (op == TOK_LT)
12254                         rez = (rez < numptr_val);
12255                 else if (op == TOK_LE)
12256                         rez = (rez <= numptr_val);
12257                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12258                         rez *= numptr_val;
12259                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12260                         rez += numptr_val;
12261                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12262                         rez -= numptr_val;
12263                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12264                         rez = numptr_val;
12265                 else if (op == TOK_CONDITIONAL_SEP) {
12266                         if (numptr_m1 == numstack) {
12267                                 /* protect $((expr : expr)) without "expr ? " */
12268                                 goto err;
12269                         }
12270                         numptr_m1->contidional_second_val_initialized = op;
12271                         numptr_m1->contidional_second_val = numptr_val;
12272                 } else if (op == TOK_CONDITIONAL) {
12273                         rez = rez ?
12274                                 numptr_val : numptr_m1->contidional_second_val;
12275                 } else if (op == TOK_EXPONENT) {
12276                         if (numptr_val < 0)
12277                                 return -3;      /* exponent less than 0 */
12278                         else {
12279                                 arith_t c = 1;
12280
12281                                 if (numptr_val)
12282                                         while (numptr_val--)
12283                                                 c *= rez;
12284                                 rez = c;
12285                         }
12286                 } else if (numptr_val==0)          /* zero divisor check */
12287                         return -2;
12288                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12289                         rez /= numptr_val;
12290                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12291                         rez %= numptr_val;
12292         }
12293         if (tok_have_assign(op)) {
12294                 char buf[sizeof(arith_t_type)*3 + 2];
12295
12296                 if (numptr_m1->var == NULL) {
12297                         /* Hmm, 1=2 ? */
12298                         goto err;
12299                 }
12300                 /* save to shell variable */
12301 #if ENABLE_ASH_MATH_SUPPORT_64
12302                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12303 #else
12304                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12305 #endif
12306                 setvar(numptr_m1->var, buf, 0);
12307                 /* after saving, make previous value for v++ or v-- */
12308                 if (op == TOK_POST_INC)
12309                         rez--;
12310                 else if (op == TOK_POST_DEC)
12311                         rez++;
12312         }
12313         numptr_m1->val = rez;
12314         /* protect geting var value, is number now */
12315         numptr_m1->var = NULL;
12316         return 0;
12317  err:
12318         return -1;
12319 }
12320
12321 /* longest must be first */
12322 static const char op_tokens[] ALIGN1 = {
12323         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12324         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12325         '<','<',    0, TOK_LSHIFT,
12326         '>','>',    0, TOK_RSHIFT,
12327         '|','|',    0, TOK_OR,
12328         '&','&',    0, TOK_AND,
12329         '!','=',    0, TOK_NE,
12330         '<','=',    0, TOK_LE,
12331         '>','=',    0, TOK_GE,
12332         '=','=',    0, TOK_EQ,
12333         '|','=',    0, TOK_OR_ASSIGN,
12334         '&','=',    0, TOK_AND_ASSIGN,
12335         '*','=',    0, TOK_MUL_ASSIGN,
12336         '/','=',    0, TOK_DIV_ASSIGN,
12337         '%','=',    0, TOK_REM_ASSIGN,
12338         '+','=',    0, TOK_PLUS_ASSIGN,
12339         '-','=',    0, TOK_MINUS_ASSIGN,
12340         '-','-',    0, TOK_POST_DEC,
12341         '^','=',    0, TOK_XOR_ASSIGN,
12342         '+','+',    0, TOK_POST_INC,
12343         '*','*',    0, TOK_EXPONENT,
12344         '!',        0, TOK_NOT,
12345         '<',        0, TOK_LT,
12346         '>',        0, TOK_GT,
12347         '=',        0, TOK_ASSIGN,
12348         '|',        0, TOK_BOR,
12349         '&',        0, TOK_BAND,
12350         '*',        0, TOK_MUL,
12351         '/',        0, TOK_DIV,
12352         '%',        0, TOK_REM,
12353         '+',        0, TOK_ADD,
12354         '-',        0, TOK_SUB,
12355         '^',        0, TOK_BXOR,
12356         /* uniq */
12357         '~',        0, TOK_BNOT,
12358         ',',        0, TOK_COMMA,
12359         '?',        0, TOK_CONDITIONAL,
12360         ':',        0, TOK_CONDITIONAL_SEP,
12361         ')',        0, TOK_RPAREN,
12362         '(',        0, TOK_LPAREN,
12363         0
12364 };
12365 /* ptr to ")" */
12366 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12367
12368 static arith_t
12369 arith(const char *expr, int *perrcode)
12370 {
12371         char arithval; /* Current character under analysis */
12372         operator lasttok, op;
12373         operator prec;
12374
12375         const char *p = endexpression;
12376         int errcode;
12377
12378         size_t datasizes = strlen(expr) + 2;
12379
12380         /* Stack of integers */
12381         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12382          * in any given correct or incorrect expression is left as an exercise to
12383          * the reader. */
12384         v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12385                                 *numstackptr = numstack;
12386         /* Stack of operator tokens */
12387         operator *stack = alloca((datasizes) * sizeof(operator)),
12388                                 *stackptr = stack;
12389
12390         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
12391         *perrcode = errcode = 0;
12392
12393         while (1) {
12394                 arithval = *expr;
12395                 if (arithval == 0) {
12396                         if (p == endexpression) {
12397                                 /* Null expression. */
12398                                 return 0;
12399                         }
12400
12401                         /* This is only reached after all tokens have been extracted from the
12402                          * input stream. If there are still tokens on the operator stack, they
12403                          * are to be applied in order. At the end, there should be a final
12404                          * result on the integer stack */
12405
12406                         if (expr != endexpression + 1) {
12407                                 /* If we haven't done so already, */
12408                                 /* append a closing right paren */
12409                                 expr = endexpression;
12410                                 /* and let the loop process it. */
12411                                 continue;
12412                         }
12413                         /* At this point, we're done with the expression. */
12414                         if (numstackptr != numstack+1) {
12415                                 /* ... but if there isn't, it's bad */
12416  err:
12417                                 return (*perrcode = -1);
12418                         }
12419                         if (numstack->var) {
12420                                 /* expression is $((var)) only, lookup now */
12421                                 errcode = arith_lookup_val(numstack);
12422                         }
12423  ret:
12424                         *perrcode = errcode;
12425                         return numstack->val;
12426                 }
12427
12428                 /* Continue processing the expression. */
12429                 if (arith_isspace(arithval)) {
12430                         /* Skip whitespace */
12431                         goto prologue;
12432                 }
12433                 p = endofname(expr);
12434                 if (p != expr) {
12435                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
12436
12437                         numstackptr->var = alloca(var_name_size);
12438                         safe_strncpy(numstackptr->var, expr, var_name_size);
12439                         expr = p;
12440  num:
12441                         numstackptr->contidional_second_val_initialized = 0;
12442                         numstackptr++;
12443                         lasttok = TOK_NUM;
12444                         continue;
12445                 }
12446                 if (isdigit(arithval)) {
12447                         numstackptr->var = NULL;
12448 #if ENABLE_ASH_MATH_SUPPORT_64
12449                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
12450 #else
12451                         numstackptr->val = strtol(expr, (char **) &expr, 0);
12452 #endif
12453                         goto num;
12454                 }
12455                 for (p = op_tokens; ; p++) {
12456                         const char *o;
12457
12458                         if (*p == 0) {
12459                                 /* strange operator not found */
12460                                 goto err;
12461                         }
12462                         for (o = expr; *p && *o == *p; p++)
12463                                 o++;
12464                         if (! *p) {
12465                                 /* found */
12466                                 expr = o - 1;
12467                                 break;
12468                         }
12469                         /* skip tail uncompared token */
12470                         while (*p)
12471                                 p++;
12472                         /* skip zero delim */
12473                         p++;
12474                 }
12475                 op = p[1];
12476
12477                 /* post grammar: a++ reduce to num */
12478                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12479                         lasttok = TOK_NUM;
12480
12481                 /* Plus and minus are binary (not unary) _only_ if the last
12482                  * token was as number, or a right paren (which pretends to be
12483                  * a number, since it evaluates to one). Think about it.
12484                  * It makes sense. */
12485                 if (lasttok != TOK_NUM) {
12486                         switch (op) {
12487                         case TOK_ADD:
12488                                 op = TOK_UPLUS;
12489                                 break;
12490                         case TOK_SUB:
12491                                 op = TOK_UMINUS;
12492                                 break;
12493                         case TOK_POST_INC:
12494                                 op = TOK_PRE_INC;
12495                                 break;
12496                         case TOK_POST_DEC:
12497                                 op = TOK_PRE_DEC;
12498                                 break;
12499                         }
12500                 }
12501                 /* We don't want a unary operator to cause recursive descent on the
12502                  * stack, because there can be many in a row and it could cause an
12503                  * operator to be evaluated before its argument is pushed onto the
12504                  * integer stack. */
12505                 /* But for binary operators, "apply" everything on the operator
12506                  * stack until we find an operator with a lesser priority than the
12507                  * one we have just extracted. */
12508                 /* Left paren is given the lowest priority so it will never be
12509                  * "applied" in this way.
12510                  * if associativity is right and priority eq, applied also skip
12511                  */
12512                 prec = PREC(op);
12513                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12514                         /* not left paren or unary */
12515                         if (lasttok != TOK_NUM) {
12516                                 /* binary op must be preceded by a num */
12517                                 goto err;
12518                         }
12519                         while (stackptr != stack) {
12520                                 if (op == TOK_RPAREN) {
12521                                         /* The algorithm employed here is simple: while we don't
12522                                          * hit an open paren nor the bottom of the stack, pop
12523                                          * tokens and apply them */
12524                                         if (stackptr[-1] == TOK_LPAREN) {
12525                                                 --stackptr;
12526                                                 /* Any operator directly after a */
12527                                                 lasttok = TOK_NUM;
12528                                                 /* close paren should consider itself binary */
12529                                                 goto prologue;
12530                                         }
12531                                 } else {
12532                                         operator prev_prec = PREC(stackptr[-1]);
12533
12534                                         convert_prec_is_assing(prec);
12535                                         convert_prec_is_assing(prev_prec);
12536                                         if (prev_prec < prec)
12537                                                 break;
12538                                         /* check right assoc */
12539                                         if (prev_prec == prec && is_right_associativity(prec))
12540                                                 break;
12541                                 }
12542                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12543                                 if (errcode) goto ret;
12544                         }
12545                         if (op == TOK_RPAREN) {
12546                                 goto err;
12547                         }
12548                 }
12549
12550                 /* Push this operator to the stack and remember it. */
12551                 *stackptr++ = lasttok = op;
12552  prologue:
12553                 ++expr;
12554         } /* while */
12555 }
12556 #endif /* ASH_MATH_SUPPORT */
12557
12558
12559 /* ============ main() and helpers */
12560
12561 /*
12562  * Called to exit the shell.
12563  */
12564 static void exitshell(void) ATTRIBUTE_NORETURN;
12565 static void
12566 exitshell(void)
12567 {
12568         struct jmploc loc;
12569         char *p;
12570         int status;
12571
12572         status = exitstatus;
12573         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12574         if (setjmp(loc.loc)) {
12575                 if (exception == EXEXIT)
12576 /* dash bug: it just does _exit(exitstatus) here
12577  * but we have to do setjobctl(0) first!
12578  * (bug is still not fixed in dash-0.5.3 - if you run dash
12579  * under Midnight Commander, on exit from dash MC is backgrounded) */
12580                         status = exitstatus;
12581                 goto out;
12582         }
12583         exception_handler = &loc;
12584         p = trap[0];
12585         if (p) {
12586                 trap[0] = NULL;
12587                 evalstring(p, 0);
12588         }
12589         flush_stdout_stderr();
12590  out:
12591         setjobctl(0);
12592         _exit(status);
12593         /* NOTREACHED */
12594 }
12595
12596 static void
12597 init(void)
12598 {
12599         /* from input.c: */
12600         basepf.nextc = basepf.buf = basebuf;
12601
12602         /* from trap.c: */
12603         signal(SIGCHLD, SIG_DFL);
12604
12605         /* from var.c: */
12606         {
12607                 char **envp;
12608                 char ppid[sizeof(int)*3 + 1];
12609                 const char *p;
12610                 struct stat st1, st2;
12611
12612                 initvar();
12613                 for (envp = environ; envp && *envp; envp++) {
12614                         if (strchr(*envp, '=')) {
12615                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12616                         }
12617                 }
12618
12619                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12620                 setvar("PPID", ppid, 0);
12621
12622                 p = lookupvar("PWD");
12623                 if (p)
12624                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12625                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12626                                 p = '\0';
12627                 setpwd(p, 0);
12628         }
12629 }
12630
12631 /*
12632  * Process the shell command line arguments.
12633  */
12634 static void
12635 procargs(int argc, char **argv)
12636 {
12637         int i;
12638         const char *xminusc;
12639         char **xargv;
12640
12641         xargv = argv;
12642         arg0 = xargv[0];
12643         if (argc > 0)
12644                 xargv++;
12645         for (i = 0; i < NOPTS; i++)
12646                 optlist[i] = 2;
12647         argptr = xargv;
12648         options(1);
12649         xargv = argptr;
12650         xminusc = minusc;
12651         if (*xargv == NULL) {
12652                 if (xminusc)
12653                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12654                 sflag = 1;
12655         }
12656         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12657                 iflag = 1;
12658         if (mflag == 2)
12659                 mflag = iflag;
12660         for (i = 0; i < NOPTS; i++)
12661                 if (optlist[i] == 2)
12662                         optlist[i] = 0;
12663 #if DEBUG == 2
12664         debug = 1;
12665 #endif
12666         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12667         if (xminusc) {
12668                 minusc = *xargv++;
12669                 if (*xargv)
12670                         goto setarg0;
12671         } else if (!sflag) {
12672                 setinputfile(*xargv, 0);
12673  setarg0:
12674                 arg0 = *xargv++;
12675                 commandname = arg0;
12676         }
12677
12678         shellparam.p = xargv;
12679 #if ENABLE_ASH_GETOPTS
12680         shellparam.optind = 1;
12681         shellparam.optoff = -1;
12682 #endif
12683         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12684         while (*xargv) {
12685                 shellparam.nparam++;
12686                 xargv++;
12687         }
12688         optschanged();
12689 }
12690
12691 /*
12692  * Read /etc/profile or .profile.
12693  */
12694 static void
12695 read_profile(const char *name)
12696 {
12697         int skip;
12698
12699         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12700                 return;
12701         skip = cmdloop(0);
12702         popfile();
12703         if (skip)
12704                 exitshell();
12705 }
12706
12707 /*
12708  * This routine is called when an error or an interrupt occurs in an
12709  * interactive shell and control is returned to the main command loop.
12710  */
12711 static void
12712 reset(void)
12713 {
12714         /* from eval.c: */
12715         evalskip = 0;
12716         loopnest = 0;
12717         /* from input.c: */
12718         parselleft = parsenleft = 0;      /* clear input buffer */
12719         popallfiles();
12720         /* from parser.c: */
12721         tokpushback = 0;
12722         checkkwd = 0;
12723         /* from redir.c: */
12724         clearredir(0);
12725 }
12726
12727 #if PROFILE
12728 static short profile_buf[16384];
12729 extern int etext();
12730 #endif
12731
12732 /*
12733  * Main routine.  We initialize things, parse the arguments, execute
12734  * profiles if we're a login shell, and then call cmdloop to execute
12735  * commands.  The setjmp call sets up the location to jump to when an
12736  * exception occurs.  When an exception occurs the variable "state"
12737  * is used to figure out how far we had gotten.
12738  */
12739 int ash_main(int argc, char **argv);
12740 int ash_main(int argc, char **argv)
12741 {
12742         char *shinit;
12743         volatile int state;
12744         struct jmploc jmploc;
12745         struct stackmark smark;
12746
12747 #if PROFILE
12748         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12749 #endif
12750
12751 #if ENABLE_FEATURE_EDITING
12752         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12753 #endif
12754         state = 0;
12755         if (setjmp(jmploc.loc)) {
12756                 int e;
12757                 int s;
12758
12759                 reset();
12760
12761                 e = exception;
12762                 if (e == EXERROR)
12763                         exitstatus = 2;
12764                 s = state;
12765                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12766                         exitshell();
12767
12768                 if (e == EXINT) {
12769                         outcslow('\n', stderr);
12770                 }
12771                 popstackmark(&smark);
12772                 FORCE_INT_ON; /* enable interrupts */
12773                 if (s == 1)
12774                         goto state1;
12775                 if (s == 2)
12776                         goto state2;
12777                 if (s == 3)
12778                         goto state3;
12779                 goto state4;
12780         }
12781         exception_handler = &jmploc;
12782 #if DEBUG
12783         opentrace();
12784         trace_puts("Shell args: ");
12785         trace_puts_args(argv);
12786 #endif
12787         rootpid = getpid();
12788
12789 #if ENABLE_ASH_RANDOM_SUPPORT
12790         rseed = rootpid + time(NULL);
12791 #endif
12792         init();
12793         setstackmark(&smark);
12794         procargs(argc, argv);
12795 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12796         if (iflag) {
12797                 const char *hp = lookupvar("HISTFILE");
12798
12799                 if (hp == NULL) {
12800                         hp = lookupvar("HOME");
12801                         if (hp != NULL) {
12802                                 char *defhp = concat_path_file(hp, ".ash_history");
12803                                 setvar("HISTFILE", defhp, 0);
12804                                 free(defhp);
12805                         }
12806                 }
12807         }
12808 #endif
12809         if (argv[0] && argv[0][0] == '-')
12810                 isloginsh = 1;
12811         if (isloginsh) {
12812                 state = 1;
12813                 read_profile("/etc/profile");
12814  state1:
12815                 state = 2;
12816                 read_profile(".profile");
12817         }
12818  state2:
12819         state = 3;
12820         if (
12821 #ifndef linux
12822          getuid() == geteuid() && getgid() == getegid() &&
12823 #endif
12824          iflag
12825         ) {
12826                 shinit = lookupvar("ENV");
12827                 if (shinit != NULL && *shinit != '\0') {
12828                         read_profile(shinit);
12829                 }
12830         }
12831  state3:
12832         state = 4;
12833         if (minusc)
12834                 evalstring(minusc, 0);
12835
12836         if (sflag || minusc == NULL) {
12837 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12838                 if ( iflag ) {
12839                         const char *hp = lookupvar("HISTFILE");
12840
12841                         if (hp != NULL)
12842                                 line_input_state->hist_file = hp;
12843                 }
12844 #endif
12845  state4: /* XXX ??? - why isn't this before the "if" statement */
12846                 cmdloop(1);
12847         }
12848 #if PROFILE
12849         monitor(0);
12850 #endif
12851 #ifdef GPROF
12852         {
12853                 extern void _mcleanup(void);
12854                 _mcleanup();
12855         }
12856 #endif
12857         exitshell();
12858         /* NOTREACHED */
12859 }
12860
12861 #if DEBUG
12862 const char *applet_name = "debug stuff usage";
12863 int main(int argc, char **argv)
12864 {
12865         return ash_main(argc, argv);
12866 }
12867 #endif
12868
12869
12870 /*-
12871  * Copyright (c) 1989, 1991, 1993, 1994
12872  *      The Regents of the University of California.  All rights reserved.
12873  *
12874  * This code is derived from software contributed to Berkeley by
12875  * Kenneth Almquist.
12876  *
12877  * Redistribution and use in source and binary forms, with or without
12878  * modification, are permitted provided that the following conditions
12879  * are met:
12880  * 1. Redistributions of source code must retain the above copyright
12881  *    notice, this list of conditions and the following disclaimer.
12882  * 2. Redistributions in binary form must reproduce the above copyright
12883  *    notice, this list of conditions and the following disclaimer in the
12884  *    documentation and/or other materials provided with the distribution.
12885  * 3. Neither the name of the University nor the names of its contributors
12886  *    may be used to endorse or promote products derived from this software
12887  *    without specific prior written permission.
12888  *
12889  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12890  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12891  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12892  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12893  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12894  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12895  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12896  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12897  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12898  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12899  * SUCH DAMAGE.
12900  */