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