remove echo_main -> bb_echo indirection
[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                 close_on_exec_on(fd);
3473                 do { /* while we are in the background */
3474                         pgrp = tcgetpgrp(fd);
3475                         if (pgrp < 0) {
3476  out:
3477                                 ash_msg("can't access tty; job control turned off");
3478                                 mflag = on = 0;
3479                                 goto close;
3480                         }
3481                         if (pgrp == getpgrp())
3482                                 break;
3483                         killpg(0, SIGTTIN);
3484                 } while (1);
3485                 initialpgrp = pgrp;
3486
3487                 setsignal(SIGTSTP);
3488                 setsignal(SIGTTOU);
3489                 setsignal(SIGTTIN);
3490                 pgrp = rootpid;
3491                 setpgid(0, pgrp);
3492                 xtcsetpgrp(fd, pgrp);
3493         } else {
3494                 /* turning job control off */
3495                 fd = ttyfd;
3496                 pgrp = initialpgrp;
3497                 /* was xtcsetpgrp, but this can make exiting ash
3498                  * with pty already deleted loop forever */
3499                 tcsetpgrp(fd, pgrp);
3500                 setpgid(0, pgrp);
3501                 setsignal(SIGTSTP);
3502                 setsignal(SIGTTOU);
3503                 setsignal(SIGTTIN);
3504  close:
3505                 close(fd);
3506                 fd = -1;
3507         }
3508         ttyfd = fd;
3509         jobctl = on;
3510 }
3511
3512 static int
3513 killcmd(int argc, char **argv)
3514 {
3515         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3516                 int i = 1;
3517                 do {
3518                         if (argv[i][0] == '%') {
3519                                 struct job *jp = getjob(argv[i], 0);
3520                                 unsigned pid = jp->ps[0].pid;
3521                                 /* Enough space for ' -NNN<nul>' */
3522                                 argv[i] = alloca(sizeof(int)*3 + 3);
3523                                 /* kill_main has matching code to expect
3524                                  * leading space. Needed to not confuse
3525                                  * negative pids with "kill -SIGNAL_NO" syntax */
3526                                 sprintf(argv[i], " -%u", pid);
3527                         }
3528                 } while (argv[++i]);
3529         }
3530         return kill_main(argc, argv);
3531 }
3532
3533 static void
3534 showpipe(struct job *jp, FILE *out)
3535 {
3536         struct procstat *sp;
3537         struct procstat *spend;
3538
3539         spend = jp->ps + jp->nprocs;
3540         for (sp = jp->ps + 1; sp < spend; sp++)
3541                 fprintf(out, " | %s", sp->cmd);
3542         outcslow('\n', out);
3543         flush_stdout_stderr();
3544 }
3545
3546
3547 static int
3548 restartjob(struct job *jp, int mode)
3549 {
3550         struct procstat *ps;
3551         int i;
3552         int status;
3553         pid_t pgid;
3554
3555         INT_OFF;
3556         if (jp->state == JOBDONE)
3557                 goto out;
3558         jp->state = JOBRUNNING;
3559         pgid = jp->ps->pid;
3560         if (mode == FORK_FG)
3561                 xtcsetpgrp(ttyfd, pgid);
3562         killpg(pgid, SIGCONT);
3563         ps = jp->ps;
3564         i = jp->nprocs;
3565         do {
3566                 if (WIFSTOPPED(ps->status)) {
3567                         ps->status = -1;
3568                 }
3569                 ps++;
3570         } while (--i);
3571  out:
3572         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3573         INT_ON;
3574         return status;
3575 }
3576
3577 static int
3578 fg_bgcmd(int argc, char **argv)
3579 {
3580         struct job *jp;
3581         FILE *out;
3582         int mode;
3583         int retval;
3584
3585         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3586         nextopt(nullstr);
3587         argv = argptr;
3588         out = stdout;
3589         do {
3590                 jp = getjob(*argv, 1);
3591                 if (mode == FORK_BG) {
3592                         set_curjob(jp, CUR_RUNNING);
3593                         fprintf(out, "[%d] ", jobno(jp));
3594                 }
3595                 outstr(jp->ps->cmd, out);
3596                 showpipe(jp, out);
3597                 retval = restartjob(jp, mode);
3598         } while (*argv && *++argv);
3599         return retval;
3600 }
3601 #endif
3602
3603 static int
3604 sprint_status(char *s, int status, int sigonly)
3605 {
3606         int col;
3607         int st;
3608
3609         col = 0;
3610         if (!WIFEXITED(status)) {
3611 #if JOBS
3612                 if (WIFSTOPPED(status))
3613                         st = WSTOPSIG(status);
3614                 else
3615 #endif
3616                         st = WTERMSIG(status);
3617                 if (sigonly) {
3618                         if (st == SIGINT || st == SIGPIPE)
3619                                 goto out;
3620 #if JOBS
3621                         if (WIFSTOPPED(status))
3622                                 goto out;
3623 #endif
3624                 }
3625                 st &= 0x7f;
3626                 col = fmtstr(s, 32, strsignal(st));
3627                 if (WCOREDUMP(status)) {
3628                         col += fmtstr(s + col, 16, " (core dumped)");
3629                 }
3630         } else if (!sigonly) {
3631                 st = WEXITSTATUS(status);
3632                 if (st)
3633                         col = fmtstr(s, 16, "Done(%d)", st);
3634                 else
3635                         col = fmtstr(s, 16, "Done");
3636         }
3637  out:
3638         return col;
3639 }
3640
3641 /*
3642  * Do a wait system call.  If job control is compiled in, we accept
3643  * stopped processes.  If block is zero, we return a value of zero
3644  * rather than blocking.
3645  *
3646  * System V doesn't have a non-blocking wait system call.  It does
3647  * have a SIGCLD signal that is sent to a process when one of it's
3648  * children dies.  The obvious way to use SIGCLD would be to install
3649  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3650  * was received, and have waitproc bump another counter when it got
3651  * the status of a process.  Waitproc would then know that a wait
3652  * system call would not block if the two counters were different.
3653  * This approach doesn't work because if a process has children that
3654  * have not been waited for, System V will send it a SIGCLD when it
3655  * installs a signal handler for SIGCLD.  What this means is that when
3656  * a child exits, the shell will be sent SIGCLD signals continuously
3657  * until is runs out of stack space, unless it does a wait call before
3658  * restoring the signal handler.  The code below takes advantage of
3659  * this (mis)feature by installing a signal handler for SIGCLD and
3660  * then checking to see whether it was called.  If there are any
3661  * children to be waited for, it will be.
3662  *
3663  * If neither SYSV nor BSD is defined, we don't implement nonblocking
3664  * waits at all.  In this case, the user will not be informed when
3665  * a background process until the next time she runs a real program
3666  * (as opposed to running a builtin command or just typing return),
3667  * and the jobs command may give out of date information.
3668  */
3669 static int
3670 waitproc(int block, int *status)
3671 {
3672         int flags = 0;
3673
3674 #if JOBS
3675         if (jobctl)
3676                 flags |= WUNTRACED;
3677 #endif
3678         if (block == 0)
3679                 flags |= WNOHANG;
3680         return wait3(status, flags, (struct rusage *)NULL);
3681 }
3682
3683 /*
3684  * Wait for a process to terminate.
3685  */
3686 static int
3687 dowait(int block, struct job *job)
3688 {
3689         int pid;
3690         int status;
3691         struct job *jp;
3692         struct job *thisjob;
3693         int state;
3694
3695         TRACE(("dowait(%d) called\n", block));
3696         pid = waitproc(block, &status);
3697         TRACE(("wait returns pid %d, status=%d\n", pid, status));
3698         if (pid <= 0)
3699                 return pid;
3700         INT_OFF;
3701         thisjob = NULL;
3702         for (jp = curjob; jp; jp = jp->prev_job) {
3703                 struct procstat *sp;
3704                 struct procstat *spend;
3705                 if (jp->state == JOBDONE)
3706                         continue;
3707                 state = JOBDONE;
3708                 spend = jp->ps + jp->nprocs;
3709                 sp = jp->ps;
3710                 do {
3711                         if (sp->pid == pid) {
3712                                 TRACE(("Job %d: changing status of proc %d "
3713                                         "from 0x%x to 0x%x\n",
3714                                         jobno(jp), pid, sp->status, status));
3715                                 sp->status = status;
3716                                 thisjob = jp;
3717                         }
3718                         if (sp->status == -1)
3719                                 state = JOBRUNNING;
3720 #if JOBS
3721                         if (state == JOBRUNNING)
3722                                 continue;
3723                         if (WIFSTOPPED(sp->status)) {
3724                                 jp->stopstatus = sp->status;
3725                                 state = JOBSTOPPED;
3726                         }
3727 #endif
3728                 } while (++sp < spend);
3729                 if (thisjob)
3730                         goto gotjob;
3731         }
3732 #if JOBS
3733         if (!WIFSTOPPED(status))
3734 #endif
3735
3736                 jobless--;
3737         goto out;
3738
3739  gotjob:
3740         if (state != JOBRUNNING) {
3741                 thisjob->changed = 1;
3742
3743                 if (thisjob->state != state) {
3744                         TRACE(("Job %d: changing state from %d to %d\n",
3745                                 jobno(thisjob), thisjob->state, state));
3746                         thisjob->state = state;
3747 #if JOBS
3748                         if (state == JOBSTOPPED) {
3749                                 set_curjob(thisjob, CUR_STOPPED);
3750                         }
3751 #endif
3752                 }
3753         }
3754
3755  out:
3756         INT_ON;
3757
3758         if (thisjob && thisjob == job) {
3759                 char s[48 + 1];
3760                 int len;
3761
3762                 len = sprint_status(s, status, 1);
3763                 if (len) {
3764                         s[len] = '\n';
3765                         s[len + 1] = 0;
3766                         out2str(s);
3767                 }
3768         }
3769         return pid;
3770 }
3771
3772 #if JOBS
3773 static void
3774 showjob(FILE *out, struct job *jp, int mode)
3775 {
3776         struct procstat *ps;
3777         struct procstat *psend;
3778         int col;
3779         int indent_col;
3780         char s[80];
3781
3782         ps = jp->ps;
3783
3784         if (mode & SHOW_PGID) {
3785                 /* just output process (group) id of pipeline */
3786                 fprintf(out, "%d\n", ps->pid);
3787                 return;
3788         }
3789
3790         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
3791         indent_col = col;
3792
3793         if (jp == curjob)
3794                 s[col - 2] = '+';
3795         else if (curjob && jp == curjob->prev_job)
3796                 s[col - 2] = '-';
3797
3798         if (mode & SHOW_PID)
3799                 col += fmtstr(s + col, 16, "%d ", ps->pid);
3800
3801         psend = ps + jp->nprocs;
3802
3803         if (jp->state == JOBRUNNING) {
3804                 strcpy(s + col, "Running");
3805                 col += sizeof("Running") - 1;
3806         } else {
3807                 int status = psend[-1].status;
3808                 if (jp->state == JOBSTOPPED)
3809                         status = jp->stopstatus;
3810                 col += sprint_status(s + col, status, 0);
3811         }
3812
3813         goto start;
3814
3815         do {
3816                 /* for each process */
3817                 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3818  start:
3819                 fprintf(out, "%s%*c%s",
3820                         s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3821                 );
3822                 if (!(mode & SHOW_PID)) {
3823                         showpipe(jp, out);
3824                         break;
3825                 }
3826                 if (++ps == psend) {
3827                         outcslow('\n', out);
3828                         break;
3829                 }
3830         } while (1);
3831
3832         jp->changed = 0;
3833
3834         if (jp->state == JOBDONE) {
3835                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3836                 freejob(jp);
3837         }
3838 }
3839
3840 /*
3841  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
3842  * statuses have changed since the last call to showjobs.
3843  */
3844 static void
3845 showjobs(FILE *out, int mode)
3846 {
3847         struct job *jp;
3848
3849         TRACE(("showjobs(%x) called\n", mode));
3850
3851         /* If not even one one job changed, there is nothing to do */
3852         while (dowait(DOWAIT_NORMAL, NULL) > 0)
3853                 continue;
3854
3855         for (jp = curjob; jp; jp = jp->prev_job) {
3856                 if (!(mode & SHOW_CHANGED) || jp->changed) {
3857                         showjob(out, jp, mode);
3858                 }
3859         }
3860 }
3861
3862 static int
3863 jobscmd(int argc, char **argv)
3864 {
3865         int mode, m;
3866
3867         mode = 0;
3868         while ((m = nextopt("lp"))) {
3869                 if (m == 'l')
3870                         mode = SHOW_PID;
3871                 else
3872                         mode = SHOW_PGID;
3873         }
3874
3875         argv = argptr;
3876         if (*argv) {
3877                 do
3878                         showjob(stdout, getjob(*argv,0), mode);
3879                 while (*++argv);
3880         } else
3881                 showjobs(stdout, mode);
3882
3883         return 0;
3884 }
3885 #endif /* JOBS */
3886
3887 static int
3888 getstatus(struct job *job)
3889 {
3890         int status;
3891         int retval;
3892
3893         status = job->ps[job->nprocs - 1].status;
3894         retval = WEXITSTATUS(status);
3895         if (!WIFEXITED(status)) {
3896 #if JOBS
3897                 retval = WSTOPSIG(status);
3898                 if (!WIFSTOPPED(status))
3899 #endif
3900                 {
3901                         /* XXX: limits number of signals */
3902                         retval = WTERMSIG(status);
3903 #if JOBS
3904                         if (retval == SIGINT)
3905                                 job->sigint = 1;
3906 #endif
3907                 }
3908                 retval += 128;
3909         }
3910         TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
3911                 jobno(job), job->nprocs, status, retval));
3912         return retval;
3913 }
3914
3915 static int
3916 waitcmd(int argc, char **argv)
3917 {
3918         struct job *job;
3919         int retval;
3920         struct job *jp;
3921
3922         EXSIGON;
3923
3924         nextopt(nullstr);
3925         retval = 0;
3926
3927         argv = argptr;
3928         if (!*argv) {
3929                 /* wait for all jobs */
3930                 for (;;) {
3931                         jp = curjob;
3932                         while (1) {
3933                                 if (!jp) {
3934                                         /* no running procs */
3935                                         goto out;
3936                                 }
3937                                 if (jp->state == JOBRUNNING)
3938                                         break;
3939                                 jp->waited = 1;
3940                                 jp = jp->prev_job;
3941                         }
3942                         dowait(DOWAIT_BLOCK, 0);
3943                 }
3944         }
3945
3946         retval = 127;
3947         do {
3948                 if (**argv != '%') {
3949                         pid_t pid = number(*argv);
3950                         job = curjob;
3951                         goto start;
3952                         do {
3953                                 if (job->ps[job->nprocs - 1].pid == pid)
3954                                         break;
3955                                 job = job->prev_job;
3956  start:
3957                                 if (!job)
3958                                         goto repeat;
3959                         } while (1);
3960                 } else
3961                         job = getjob(*argv, 0);
3962                 /* loop until process terminated or stopped */
3963                 while (job->state == JOBRUNNING)
3964                         dowait(DOWAIT_BLOCK, 0);
3965                 job->waited = 1;
3966                 retval = getstatus(job);
3967  repeat:
3968                 ;
3969         } while (*++argv);
3970
3971  out:
3972         return retval;
3973 }
3974
3975 static struct job *
3976 growjobtab(void)
3977 {
3978         size_t len;
3979         ptrdiff_t offset;
3980         struct job *jp, *jq;
3981
3982         len = njobs * sizeof(*jp);
3983         jq = jobtab;
3984         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
3985
3986         offset = (char *)jp - (char *)jq;
3987         if (offset) {
3988                 /* Relocate pointers */
3989                 size_t l = len;
3990
3991                 jq = (struct job *)((char *)jq + l);
3992                 while (l) {
3993                         l -= sizeof(*jp);
3994                         jq--;
3995 #define joff(p) ((struct job *)((char *)(p) + l))
3996 #define jmove(p) (p) = (void *)((char *)(p) + offset)
3997                         if (joff(jp)->ps == &jq->ps0)
3998                                 jmove(joff(jp)->ps);
3999                         if (joff(jp)->prev_job)
4000                                 jmove(joff(jp)->prev_job);
4001                 }
4002                 if (curjob)
4003                         jmove(curjob);
4004 #undef joff
4005 #undef jmove
4006         }
4007
4008         njobs += 4;
4009         jobtab = jp;
4010         jp = (struct job *)((char *)jp + len);
4011         jq = jp + 3;
4012         do {
4013                 jq->used = 0;
4014         } while (--jq >= jp);
4015         return jp;
4016 }
4017
4018 /*
4019  * Return a new job structure.
4020  * Called with interrupts off.
4021  */
4022 static struct job *
4023 makejob(union node *node, int nprocs)
4024 {
4025         int i;
4026         struct job *jp;
4027
4028         for (i = njobs, jp = jobtab; ; jp++) {
4029                 if (--i < 0) {
4030                         jp = growjobtab();
4031                         break;
4032                 }
4033                 if (jp->used == 0)
4034                         break;
4035                 if (jp->state != JOBDONE || !jp->waited)
4036                         continue;
4037 #if JOBS
4038                 if (jobctl)
4039                         continue;
4040 #endif
4041                 freejob(jp);
4042                 break;
4043         }
4044         memset(jp, 0, sizeof(*jp));
4045 #if JOBS
4046         /* jp->jobctl is a bitfield.
4047          * "jp->jobctl |= jobctl" likely to give awful code */
4048         if (jobctl)
4049                 jp->jobctl = 1;
4050 #endif
4051         jp->prev_job = curjob;
4052         curjob = jp;
4053         jp->used = 1;
4054         jp->ps = &jp->ps0;
4055         if (nprocs > 1) {
4056                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4057         }
4058         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
4059                                 jobno(jp)));
4060         return jp;
4061 }
4062
4063 #if JOBS
4064 /*
4065  * Return a string identifying a command (to be printed by the
4066  * jobs command).
4067  */
4068 static char *cmdnextc;
4069
4070 static void
4071 cmdputs(const char *s)
4072 {
4073         const char *p, *str;
4074         char c, cc[2] = " ";
4075         char *nextc;
4076         int subtype = 0;
4077         int quoted = 0;
4078         static const char vstype[VSTYPE + 1][4] = {
4079                 "", "}", "-", "+", "?", "=",
4080                 "%", "%%", "#", "##"
4081         };
4082
4083         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4084         p = s;
4085         while ((c = *p++) != 0) {
4086                 str = 0;
4087                 switch (c) {
4088                 case CTLESC:
4089                         c = *p++;
4090                         break;
4091                 case CTLVAR:
4092                         subtype = *p++;
4093                         if ((subtype & VSTYPE) == VSLENGTH)
4094                                 str = "${#";
4095                         else
4096                                 str = "${";
4097                         if (!(subtype & VSQUOTE) == !(quoted & 1))
4098                                 goto dostr;
4099                         quoted ^= 1;
4100                         c = '"';
4101                         break;
4102                 case CTLENDVAR:
4103                         str = "\"}" + !(quoted & 1);
4104                         quoted >>= 1;
4105                         subtype = 0;
4106                         goto dostr;
4107                 case CTLBACKQ:
4108                         str = "$(...)";
4109                         goto dostr;
4110                 case CTLBACKQ+CTLQUOTE:
4111                         str = "\"$(...)\"";
4112                         goto dostr;
4113 #if ENABLE_ASH_MATH_SUPPORT
4114                 case CTLARI:
4115                         str = "$((";
4116                         goto dostr;
4117                 case CTLENDARI:
4118                         str = "))";
4119                         goto dostr;
4120 #endif
4121                 case CTLQUOTEMARK:
4122                         quoted ^= 1;
4123                         c = '"';
4124                         break;
4125                 case '=':
4126                         if (subtype == 0)
4127                                 break;
4128                         if ((subtype & VSTYPE) != VSNORMAL)
4129                                 quoted <<= 1;
4130                         str = vstype[subtype & VSTYPE];
4131                         if (subtype & VSNUL)
4132                                 c = ':';
4133                         else
4134                                 goto checkstr;
4135                         break;
4136                 case '\'':
4137                 case '\\':
4138                 case '"':
4139                 case '$':
4140                         /* These can only happen inside quotes */
4141                         cc[0] = c;
4142                         str = cc;
4143                         c = '\\';
4144                         break;
4145                 default:
4146                         break;
4147                 }
4148                 USTPUTC(c, nextc);
4149  checkstr:
4150                 if (!str)
4151                         continue;
4152  dostr:
4153                 while ((c = *str++)) {
4154                         USTPUTC(c, nextc);
4155                 }
4156         }
4157         if (quoted & 1) {
4158                 USTPUTC('"', nextc);
4159         }
4160         *nextc = 0;
4161         cmdnextc = nextc;
4162 }
4163
4164 /* cmdtxt() and cmdlist() call each other */
4165 static void cmdtxt(union node *n);
4166
4167 static void
4168 cmdlist(union node *np, int sep)
4169 {
4170         for (; np; np = np->narg.next) {
4171                 if (!sep)
4172                         cmdputs(" ");
4173                 cmdtxt(np);
4174                 if (sep && np->narg.next)
4175                         cmdputs(" ");
4176         }
4177 }
4178
4179 static void
4180 cmdtxt(union node *n)
4181 {
4182         union node *np;
4183         struct nodelist *lp;
4184         const char *p;
4185         char s[2];
4186
4187         if (!n)
4188                 return;
4189         switch (n->type) {
4190         default:
4191 #if DEBUG
4192                 abort();
4193 #endif
4194         case NPIPE:
4195                 lp = n->npipe.cmdlist;
4196                 for (;;) {
4197                         cmdtxt(lp->n);
4198                         lp = lp->next;
4199                         if (!lp)
4200                                 break;
4201                         cmdputs(" | ");
4202                 }
4203                 break;
4204         case NSEMI:
4205                 p = "; ";
4206                 goto binop;
4207         case NAND:
4208                 p = " && ";
4209                 goto binop;
4210         case NOR:
4211                 p = " || ";
4212  binop:
4213                 cmdtxt(n->nbinary.ch1);
4214                 cmdputs(p);
4215                 n = n->nbinary.ch2;
4216                 goto donode;
4217         case NREDIR:
4218         case NBACKGND:
4219                 n = n->nredir.n;
4220                 goto donode;
4221         case NNOT:
4222                 cmdputs("!");
4223                 n = n->nnot.com;
4224  donode:
4225                 cmdtxt(n);
4226                 break;
4227         case NIF:
4228                 cmdputs("if ");
4229                 cmdtxt(n->nif.test);
4230                 cmdputs("; then ");
4231                 n = n->nif.ifpart;
4232                 if (n->nif.elsepart) {
4233                         cmdtxt(n);
4234                         cmdputs("; else ");
4235                         n = n->nif.elsepart;
4236                 }
4237                 p = "; fi";
4238                 goto dotail;
4239         case NSUBSHELL:
4240                 cmdputs("(");
4241                 n = n->nredir.n;
4242                 p = ")";
4243                 goto dotail;
4244         case NWHILE:
4245                 p = "while ";
4246                 goto until;
4247         case NUNTIL:
4248                 p = "until ";
4249  until:
4250                 cmdputs(p);
4251                 cmdtxt(n->nbinary.ch1);
4252                 n = n->nbinary.ch2;
4253                 p = "; done";
4254  dodo:
4255                 cmdputs("; do ");
4256  dotail:
4257                 cmdtxt(n);
4258                 goto dotail2;
4259         case NFOR:
4260                 cmdputs("for ");
4261                 cmdputs(n->nfor.var);
4262                 cmdputs(" in ");
4263                 cmdlist(n->nfor.args, 1);
4264                 n = n->nfor.body;
4265                 p = "; done";
4266                 goto dodo;
4267         case NDEFUN:
4268                 cmdputs(n->narg.text);
4269                 p = "() { ... }";
4270                 goto dotail2;
4271         case NCMD:
4272                 cmdlist(n->ncmd.args, 1);
4273                 cmdlist(n->ncmd.redirect, 0);
4274                 break;
4275         case NARG:
4276                 p = n->narg.text;
4277  dotail2:
4278                 cmdputs(p);
4279                 break;
4280         case NHERE:
4281         case NXHERE:
4282                 p = "<<...";
4283                 goto dotail2;
4284         case NCASE:
4285                 cmdputs("case ");
4286                 cmdputs(n->ncase.expr->narg.text);
4287                 cmdputs(" in ");
4288                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4289                         cmdtxt(np->nclist.pattern);
4290                         cmdputs(") ");
4291                         cmdtxt(np->nclist.body);
4292                         cmdputs(";; ");
4293                 }
4294                 p = "esac";
4295                 goto dotail2;
4296         case NTO:
4297                 p = ">";
4298                 goto redir;
4299         case NCLOBBER:
4300                 p = ">|";
4301                 goto redir;
4302         case NAPPEND:
4303                 p = ">>";
4304                 goto redir;
4305         case NTOFD:
4306                 p = ">&";
4307                 goto redir;
4308         case NFROM:
4309                 p = "<";
4310                 goto redir;
4311         case NFROMFD:
4312                 p = "<&";
4313                 goto redir;
4314         case NFROMTO:
4315                 p = "<>";
4316  redir:
4317                 s[0] = n->nfile.fd + '0';
4318                 s[1] = '\0';
4319                 cmdputs(s);
4320                 cmdputs(p);
4321                 if (n->type == NTOFD || n->type == NFROMFD) {
4322                         s[0] = n->ndup.dupfd + '0';
4323                         p = s;
4324                         goto dotail2;
4325                 }
4326                 n = n->nfile.fname;
4327                 goto donode;
4328         }
4329 }
4330
4331 static char *
4332 commandtext(union node *n)
4333 {
4334         char *name;
4335
4336         STARTSTACKSTR(cmdnextc);
4337         cmdtxt(n);
4338         name = stackblock();
4339         TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4340                         name, cmdnextc, cmdnextc));
4341         return ckstrdup(name);
4342 }
4343 #endif /* JOBS */
4344
4345 /*
4346  * Fork off a subshell.  If we are doing job control, give the subshell its
4347  * own process group.  Jp is a job structure that the job is to be added to.
4348  * N is the command that will be evaluated by the child.  Both jp and n may
4349  * be NULL.  The mode parameter can be one of the following:
4350  *      FORK_FG - Fork off a foreground process.
4351  *      FORK_BG - Fork off a background process.
4352  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4353  *                   process group even if job control is on.
4354  *
4355  * When job control is turned off, background processes have their standard
4356  * input redirected to /dev/null (except for the second and later processes
4357  * in a pipeline).
4358  *
4359  * Called with interrupts off.
4360  */
4361 /*
4362  * Clear traps on a fork.
4363  */
4364 static void
4365 clear_traps(void)
4366 {
4367         char **tp;
4368
4369         for (tp = trap; tp < &trap[NSIG]; tp++) {
4370                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
4371                         INT_OFF;
4372                         free(*tp);
4373                         *tp = NULL;
4374                         if (tp != &trap[0])
4375                                 setsignal(tp - trap);
4376                         INT_ON;
4377                 }
4378         }
4379 }
4380
4381 /* Lives far away from here, needed for forkchild */
4382 static void closescript(void);
4383
4384 /* Called after fork(), in child */
4385 static void
4386 forkchild(struct job *jp, union node *n, int mode)
4387 {
4388         int oldlvl;
4389
4390         TRACE(("Child shell %d\n", getpid()));
4391         oldlvl = shlvl;
4392         shlvl++;
4393
4394         closescript();
4395         clear_traps();
4396 #if JOBS
4397         /* do job control only in root shell */
4398         jobctl = 0;
4399         if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4400                 pid_t pgrp;
4401
4402                 if (jp->nprocs == 0)
4403                         pgrp = getpid();
4404                 else
4405                         pgrp = jp->ps[0].pid;
4406                 /* This can fail because we are doing it in the parent also */
4407                 (void)setpgid(0, pgrp);
4408                 if (mode == FORK_FG)
4409                         xtcsetpgrp(ttyfd, pgrp);
4410                 setsignal(SIGTSTP);
4411                 setsignal(SIGTTOU);
4412         } else
4413 #endif
4414         if (mode == FORK_BG) {
4415                 ignoresig(SIGINT);
4416                 ignoresig(SIGQUIT);
4417                 if (jp->nprocs == 0) {
4418                         close(0);
4419                         if (open(bb_dev_null, O_RDONLY) != 0)
4420                                 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4421                 }
4422         }
4423         if (!oldlvl && iflag) {
4424                 setsignal(SIGINT);
4425                 setsignal(SIGQUIT);
4426                 setsignal(SIGTERM);
4427         }
4428         for (jp = curjob; jp; jp = jp->prev_job)
4429                 freejob(jp);
4430         jobless = 0;
4431 }
4432
4433 /* Called after fork(), in parent */
4434 static void
4435 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4436 {
4437         TRACE(("In parent shell: child = %d\n", pid));
4438         if (!jp) {
4439                 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
4440                 jobless++;
4441                 return;
4442         }
4443 #if JOBS
4444         if (mode != FORK_NOJOB && jp->jobctl) {
4445                 int pgrp;
4446
4447                 if (jp->nprocs == 0)
4448                         pgrp = pid;
4449                 else
4450                         pgrp = jp->ps[0].pid;
4451                 /* This can fail because we are doing it in the child also */
4452                 setpgid(pid, pgrp);
4453         }
4454 #endif
4455         if (mode == FORK_BG) {
4456                 backgndpid = pid;               /* set $! */
4457                 set_curjob(jp, CUR_RUNNING);
4458         }
4459         if (jp) {
4460                 struct procstat *ps = &jp->ps[jp->nprocs++];
4461                 ps->pid = pid;
4462                 ps->status = -1;
4463                 ps->cmd = nullstr;
4464 #if JOBS
4465                 if (jobctl && n)
4466                         ps->cmd = commandtext(n);
4467 #endif
4468         }
4469 }
4470
4471 static int
4472 forkshell(struct job *jp, union node *n, int mode)
4473 {
4474         int pid;
4475
4476         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4477         pid = fork();
4478         if (pid < 0) {
4479                 TRACE(("Fork failed, errno=%d", errno));
4480                 if (jp)
4481                         freejob(jp);
4482                 ash_msg_and_raise_error("cannot fork");
4483         }
4484         if (pid == 0)
4485                 forkchild(jp, n, mode);
4486         else
4487                 forkparent(jp, n, mode, pid);
4488         return pid;
4489 }
4490
4491 /*
4492  * Wait for job to finish.
4493  *
4494  * Under job control we have the problem that while a child process is
4495  * running interrupts generated by the user are sent to the child but not
4496  * to the shell.  This means that an infinite loop started by an inter-
4497  * active user may be hard to kill.  With job control turned off, an
4498  * interactive user may place an interactive program inside a loop.  If
4499  * the interactive program catches interrupts, the user doesn't want
4500  * these interrupts to also abort the loop.  The approach we take here
4501  * is to have the shell ignore interrupt signals while waiting for a
4502  * foreground process to terminate, and then send itself an interrupt
4503  * signal if the child process was terminated by an interrupt signal.
4504  * Unfortunately, some programs want to do a bit of cleanup and then
4505  * exit on interrupt; unless these processes terminate themselves by
4506  * sending a signal to themselves (instead of calling exit) they will
4507  * confuse this approach.
4508  *
4509  * Called with interrupts off.
4510  */
4511 static int
4512 waitforjob(struct job *jp)
4513 {
4514         int st;
4515
4516         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4517         while (jp->state == JOBRUNNING) {
4518                 dowait(DOWAIT_BLOCK, jp);
4519         }
4520         st = getstatus(jp);
4521 #if JOBS
4522         if (jp->jobctl) {
4523                 xtcsetpgrp(ttyfd, rootpid);
4524                 /*
4525                  * This is truly gross.
4526                  * If we're doing job control, then we did a TIOCSPGRP which
4527                  * caused us (the shell) to no longer be in the controlling
4528                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
4529                  * intuit from the subprocess exit status whether a SIGINT
4530                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
4531                  */
4532                 if (jp->sigint)
4533                         raise(SIGINT);
4534         }
4535         if (jp->state == JOBDONE)
4536 #endif
4537                 freejob(jp);
4538         return st;
4539 }
4540
4541 /*
4542  * return 1 if there are stopped jobs, otherwise 0
4543  */
4544 static int
4545 stoppedjobs(void)
4546 {
4547         struct job *jp;
4548         int retval;
4549
4550         retval = 0;
4551         if (job_warning)
4552                 goto out;
4553         jp = curjob;
4554         if (jp && jp->state == JOBSTOPPED) {
4555                 out2str("You have stopped jobs.\n");
4556                 job_warning = 2;
4557                 retval++;
4558         }
4559  out:
4560         return retval;
4561 }
4562
4563
4564 /* ============ redir.c
4565  *
4566  * Code for dealing with input/output redirection.
4567  */
4568
4569 #define EMPTY -2                /* marks an unused slot in redirtab */
4570 #define CLOSED -3               /* marks a slot of previously-closed fd */
4571 #ifndef PIPE_BUF
4572 # define PIPESIZE 4096          /* amount of buffering in a pipe */
4573 #else
4574 # define PIPESIZE PIPE_BUF
4575 #endif
4576
4577 /*
4578  * Open a file in noclobber mode.
4579  * The code was copied from bash.
4580  */
4581 static int
4582 noclobberopen(const char *fname)
4583 {
4584         int r, fd;
4585         struct stat finfo, finfo2;
4586
4587         /*
4588          * If the file exists and is a regular file, return an error
4589          * immediately.
4590          */
4591         r = stat(fname, &finfo);
4592         if (r == 0 && S_ISREG(finfo.st_mode)) {
4593                 errno = EEXIST;
4594                 return -1;
4595         }
4596
4597         /*
4598          * If the file was not present (r != 0), make sure we open it
4599          * exclusively so that if it is created before we open it, our open
4600          * will fail.  Make sure that we do not truncate an existing file.
4601          * Note that we don't turn on O_EXCL unless the stat failed -- if the
4602          * file was not a regular file, we leave O_EXCL off.
4603          */
4604         if (r != 0)
4605                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4606         fd = open(fname, O_WRONLY|O_CREAT, 0666);
4607
4608         /* If the open failed, return the file descriptor right away. */
4609         if (fd < 0)
4610                 return fd;
4611
4612         /*
4613          * OK, the open succeeded, but the file may have been changed from a
4614          * non-regular file to a regular file between the stat and the open.
4615          * We are assuming that the O_EXCL open handles the case where FILENAME
4616          * did not exist and is symlinked to an existing file between the stat
4617          * and open.
4618          */
4619
4620         /*
4621          * If we can open it and fstat the file descriptor, and neither check
4622          * revealed that it was a regular file, and the file has not been
4623          * replaced, return the file descriptor.
4624          */
4625         if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4626          && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4627                 return fd;
4628
4629         /* The file has been replaced.  badness. */
4630         close(fd);
4631         errno = EEXIST;
4632         return -1;
4633 }
4634
4635 /*
4636  * Handle here documents.  Normally we fork off a process to write the
4637  * data to a pipe.  If the document is short, we can stuff the data in
4638  * the pipe without forking.
4639  */
4640 /* openhere needs this forward reference */
4641 static void expandhere(union node *arg, int fd);
4642 static int
4643 openhere(union node *redir)
4644 {
4645         int pip[2];
4646         size_t len = 0;
4647
4648         if (pipe(pip) < 0)
4649                 ash_msg_and_raise_error("pipe call failed");
4650         if (redir->type == NHERE) {
4651                 len = strlen(redir->nhere.doc->narg.text);
4652                 if (len <= PIPESIZE) {
4653                         full_write(pip[1], redir->nhere.doc->narg.text, len);
4654                         goto out;
4655                 }
4656         }
4657         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4658                 close(pip[0]);
4659                 signal(SIGINT, SIG_IGN);
4660                 signal(SIGQUIT, SIG_IGN);
4661                 signal(SIGHUP, SIG_IGN);
4662 #ifdef SIGTSTP
4663                 signal(SIGTSTP, SIG_IGN);
4664 #endif
4665                 signal(SIGPIPE, SIG_DFL);
4666                 if (redir->type == NHERE)
4667                         full_write(pip[1], redir->nhere.doc->narg.text, len);
4668                 else
4669                         expandhere(redir->nhere.doc, pip[1]);
4670                 _exit(0);
4671         }
4672  out:
4673         close(pip[1]);
4674         return pip[0];
4675 }
4676
4677 static int
4678 openredirect(union node *redir)
4679 {
4680         char *fname;
4681         int f;
4682
4683         switch (redir->nfile.type) {
4684         case NFROM:
4685                 fname = redir->nfile.expfname;
4686                 f = open(fname, O_RDONLY);
4687                 if (f < 0)
4688                         goto eopen;
4689                 break;
4690         case NFROMTO:
4691                 fname = redir->nfile.expfname;
4692                 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4693                 if (f < 0)
4694                         goto ecreate;
4695                 break;
4696         case NTO:
4697                 /* Take care of noclobber mode. */
4698                 if (Cflag) {
4699                         fname = redir->nfile.expfname;
4700                         f = noclobberopen(fname);
4701                         if (f < 0)
4702                                 goto ecreate;
4703                         break;
4704                 }
4705                 /* FALLTHROUGH */
4706         case NCLOBBER:
4707                 fname = redir->nfile.expfname;
4708                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4709                 if (f < 0)
4710                         goto ecreate;
4711                 break;
4712         case NAPPEND:
4713                 fname = redir->nfile.expfname;
4714                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4715                 if (f < 0)
4716                         goto ecreate;
4717                 break;
4718         default:
4719 #if DEBUG
4720                 abort();
4721 #endif
4722                 /* Fall through to eliminate warning. */
4723         case NTOFD:
4724         case NFROMFD:
4725                 f = -1;
4726                 break;
4727         case NHERE:
4728         case NXHERE:
4729                 f = openhere(redir);
4730                 break;
4731         }
4732
4733         return f;
4734  ecreate:
4735         ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4736  eopen:
4737         ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
4738 }
4739
4740 /*
4741  * Copy a file descriptor to be >= to.  Returns -1
4742  * if the source file descriptor is closed, EMPTY if there are no unused
4743  * file descriptors left.
4744  */
4745 static int
4746 copyfd(int from, int to)
4747 {
4748         int newfd;
4749
4750         newfd = fcntl(from, F_DUPFD, to);
4751         if (newfd < 0) {
4752                 if (errno == EMFILE)
4753                         return EMPTY;
4754                 ash_msg_and_raise_error("%d: %m", from);
4755         }
4756         return newfd;
4757 }
4758
4759 static void
4760 dupredirect(union node *redir, int f)
4761 {
4762         int fd = redir->nfile.fd;
4763
4764         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4765                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
4766                         copyfd(redir->ndup.dupfd, fd);
4767                 }
4768                 return;
4769         }
4770
4771         if (f != fd) {
4772                 copyfd(f, fd);
4773                 close(f);
4774         }
4775 }
4776
4777 /*
4778  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
4779  * old file descriptors are stashed away so that the redirection can be
4780  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
4781  * standard output, and the standard error if it becomes a duplicate of
4782  * stdout, is saved in memory.
4783  */
4784 /* flags passed to redirect */
4785 #define REDIR_PUSH    01        /* save previous values of file descriptors */
4786 #define REDIR_SAVEFD2 03        /* set preverrout */
4787 static void
4788 redirect(union node *redir, int flags)
4789 {
4790         union node *n;
4791         struct redirtab *sv;
4792         int i;
4793         int fd;
4794         int newfd;
4795
4796         nullredirs++;
4797         if (!redir) {
4798                 return;
4799         }
4800         sv = NULL;
4801         INT_OFF;
4802         if (flags & REDIR_PUSH) {
4803                 sv = ckmalloc(sizeof(*sv));
4804                 sv->next = redirlist;
4805                 redirlist = sv;
4806                 sv->nullredirs = nullredirs - 1;
4807                 for (i = 0; i < 10; i++)
4808                         sv->renamed[i] = EMPTY;
4809                 nullredirs = 0;
4810         }
4811         n = redir;
4812         do {
4813                 fd = n->nfile.fd;
4814                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4815                  && n->ndup.dupfd == fd)
4816                         continue; /* redirect from/to same file descriptor */
4817
4818                 newfd = openredirect(n);
4819                 if (fd == newfd) {
4820                         /* Descriptor wasn't open before redirect.
4821                          * Mark it for close in the future */
4822                         if (sv && sv->renamed[fd] == EMPTY)
4823                                 sv->renamed[fd] = CLOSED;
4824                         continue;
4825                 }
4826                 if (sv && sv->renamed[fd] == EMPTY) {
4827                         i = fcntl(fd, F_DUPFD, 10);
4828
4829                         if (i == -1) {
4830                                 i = errno;
4831                                 if (i != EBADF) {
4832                                         close(newfd);
4833                                         errno = i;
4834                                         ash_msg_and_raise_error("%d: %m", fd);
4835                                         /* NOTREACHED */
4836                                 }
4837                         } else {
4838                                 sv->renamed[fd] = i;
4839                                 close(fd);
4840                         }
4841                 } else {
4842                         close(fd);
4843                 }
4844                 dupredirect(n, newfd);
4845         } while ((n = n->nfile.next));
4846         INT_ON;
4847         if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0)
4848                 preverrout_fd = sv->renamed[2];
4849 }
4850
4851 /*
4852  * Undo the effects of the last redirection.
4853  */
4854 static void
4855 popredir(int drop)
4856 {
4857         struct redirtab *rp;
4858         int i;
4859
4860         if (--nullredirs >= 0)
4861                 return;
4862         INT_OFF;
4863         rp = redirlist;
4864         for (i = 0; i < 10; i++) {
4865                 if (rp->renamed[i] == CLOSED) {
4866                         if (!drop)
4867                                 close(i);
4868                         continue;
4869                 }
4870                 if (rp->renamed[i] != EMPTY) {
4871                         if (!drop) {
4872                                 close(i);
4873                                 copyfd(rp->renamed[i], i);
4874                         }
4875                         close(rp->renamed[i]);
4876                 }
4877         }
4878         redirlist = rp->next;
4879         nullredirs = rp->nullredirs;
4880         free(rp);
4881         INT_ON;
4882 }
4883
4884 /*
4885  * Undo all redirections.  Called on error or interrupt.
4886  */
4887
4888 /*
4889  * Discard all saved file descriptors.
4890  */
4891 static void
4892 clearredir(int drop)
4893 {
4894         for (;;) {
4895                 nullredirs = 0;
4896                 if (!redirlist)
4897                         break;
4898                 popredir(drop);
4899         }
4900 }
4901
4902 static int
4903 redirectsafe(union node *redir, int flags)
4904 {
4905         int err;
4906         volatile int saveint;
4907         struct jmploc *volatile savehandler = exception_handler;
4908         struct jmploc jmploc;
4909
4910         SAVE_INT(saveint);
4911         err = setjmp(jmploc.loc) * 2;
4912         if (!err) {
4913                 exception_handler = &jmploc;
4914                 redirect(redir, flags);
4915         }
4916         exception_handler = savehandler;
4917         if (err && exception != EXERROR)
4918                 longjmp(exception_handler->loc, 1);
4919         RESTORE_INT(saveint);
4920         return err;
4921 }
4922
4923
4924 /* ============ Routines to expand arguments to commands
4925  *
4926  * We have to deal with backquotes, shell variables, and file metacharacters.
4927  */
4928
4929 /*
4930  * expandarg flags
4931  */
4932 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
4933 #define EXP_TILDE       0x2     /* do normal tilde expansion */
4934 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
4935 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
4936 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
4937 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
4938 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
4939 #define EXP_WORD        0x80    /* expand word in parameter expansion */
4940 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
4941 /*
4942  * _rmescape() flags
4943  */
4944 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
4945 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
4946 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
4947 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
4948 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
4949
4950 /*
4951  * Structure specifying which parts of the string should be searched
4952  * for IFS characters.
4953  */
4954 struct ifsregion {
4955         struct ifsregion *next; /* next region in list */
4956         int begoff;             /* offset of start of region */
4957         int endoff;             /* offset of end of region */
4958         int nulonly;            /* search for nul bytes only */
4959 };
4960
4961 struct arglist {
4962         struct strlist *list;
4963         struct strlist **lastp;
4964 };
4965
4966 /* output of current string */
4967 static char *expdest;
4968 /* list of back quote expressions */
4969 static struct nodelist *argbackq;
4970 /* first struct in list of ifs regions */
4971 static struct ifsregion ifsfirst;
4972 /* last struct in list */
4973 static struct ifsregion *ifslastp;
4974 /* holds expanded arg list */
4975 static struct arglist exparg;
4976
4977 /*
4978  * Our own itoa().
4979  */
4980 static int
4981 cvtnum(arith_t num)
4982 {
4983         int len;
4984
4985         expdest = makestrspace(32, expdest);
4986 #if ENABLE_ASH_MATH_SUPPORT_64
4987         len = fmtstr(expdest, 32, "%lld", (long long) num);
4988 #else
4989         len = fmtstr(expdest, 32, "%ld", num);
4990 #endif
4991         STADJUST(len, expdest);
4992         return len;
4993 }
4994
4995 static size_t
4996 esclen(const char *start, const char *p)
4997 {
4998         size_t esc = 0;
4999
5000         while (p > start && *--p == CTLESC) {
5001                 esc++;
5002         }
5003         return esc;
5004 }
5005
5006 /*
5007  * Remove any CTLESC characters from a string.
5008  */
5009 static char *
5010 _rmescapes(char *str, int flag)
5011 {
5012         static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5013
5014         char *p, *q, *r;
5015         unsigned inquotes;
5016         int notescaped;
5017         int globbing;
5018
5019         p = strpbrk(str, qchars);
5020         if (!p) {
5021                 return str;
5022         }
5023         q = p;
5024         r = str;
5025         if (flag & RMESCAPE_ALLOC) {
5026                 size_t len = p - str;
5027                 size_t fulllen = len + strlen(p) + 1;
5028
5029                 if (flag & RMESCAPE_GROW) {
5030                         r = makestrspace(fulllen, expdest);
5031                 } else if (flag & RMESCAPE_HEAP) {
5032                         r = ckmalloc(fulllen);
5033                 } else {
5034                         r = stalloc(fulllen);
5035                 }
5036                 q = r;
5037                 if (len > 0) {
5038                         q = memcpy(q, str, len) + len;
5039                 }
5040         }
5041         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5042         globbing = flag & RMESCAPE_GLOB;
5043         notescaped = globbing;
5044         while (*p) {
5045                 if (*p == CTLQUOTEMARK) {
5046                         inquotes = ~inquotes;
5047                         p++;
5048                         notescaped = globbing;
5049                         continue;
5050                 }
5051                 if (*p == '\\') {
5052                         /* naked back slash */
5053                         notescaped = 0;
5054                         goto copy;
5055                 }
5056                 if (*p == CTLESC) {
5057                         p++;
5058                         if (notescaped && inquotes && *p != '/') {
5059                                 *q++ = '\\';
5060                         }
5061                 }
5062                 notescaped = globbing;
5063  copy:
5064                 *q++ = *p++;
5065         }
5066         *q = '\0';
5067         if (flag & RMESCAPE_GROW) {
5068                 expdest = r;
5069                 STADJUST(q - r + 1, expdest);
5070         }
5071         return r;
5072 }
5073 #define rmescapes(p) _rmescapes((p), 0)
5074
5075 #define pmatch(a, b) !fnmatch((a), (b), 0)
5076
5077 /*
5078  * Prepare a pattern for a expmeta (internal glob(3)) call.
5079  *
5080  * Returns an stalloced string.
5081  */
5082 static char *
5083 preglob(const char *pattern, int quoted, int flag)
5084 {
5085         flag |= RMESCAPE_GLOB;
5086         if (quoted) {
5087                 flag |= RMESCAPE_QUOTED;
5088         }
5089         return _rmescapes((char *)pattern, flag);
5090 }
5091
5092 /*
5093  * Put a string on the stack.
5094  */
5095 static void
5096 memtodest(const char *p, size_t len, int syntax, int quotes)
5097 {
5098         char *q = expdest;
5099
5100         q = makestrspace(len * 2, q);
5101
5102         while (len--) {
5103                 int c = signed_char2int(*p++);
5104                 if (!c)
5105                         continue;
5106                 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5107                         USTPUTC(CTLESC, q);
5108                 USTPUTC(c, q);
5109         }
5110
5111         expdest = q;
5112 }
5113
5114 static void
5115 strtodest(const char *p, int syntax, int quotes)
5116 {
5117         memtodest(p, strlen(p), syntax, quotes);
5118 }
5119
5120 /*
5121  * Record the fact that we have to scan this region of the
5122  * string for IFS characters.
5123  */
5124 static void
5125 recordregion(int start, int end, int nulonly)
5126 {
5127         struct ifsregion *ifsp;
5128
5129         if (ifslastp == NULL) {
5130                 ifsp = &ifsfirst;
5131         } else {
5132                 INT_OFF;
5133                 ifsp = ckmalloc(sizeof(*ifsp));
5134                 ifsp->next = NULL;
5135                 ifslastp->next = ifsp;
5136                 INT_ON;
5137         }
5138         ifslastp = ifsp;
5139         ifslastp->begoff = start;
5140         ifslastp->endoff = end;
5141         ifslastp->nulonly = nulonly;
5142 }
5143
5144 static void
5145 removerecordregions(int endoff)
5146 {
5147         if (ifslastp == NULL)
5148                 return;
5149
5150         if (ifsfirst.endoff > endoff) {
5151                 while (ifsfirst.next != NULL) {
5152                         struct ifsregion *ifsp;
5153                         INT_OFF;
5154                         ifsp = ifsfirst.next->next;
5155                         free(ifsfirst.next);
5156                         ifsfirst.next = ifsp;
5157                         INT_ON;
5158                 }
5159                 if (ifsfirst.begoff > endoff)
5160                         ifslastp = NULL;
5161                 else {
5162                         ifslastp = &ifsfirst;
5163                         ifsfirst.endoff = endoff;
5164                 }
5165                 return;
5166         }
5167
5168         ifslastp = &ifsfirst;
5169         while (ifslastp->next && ifslastp->next->begoff < endoff)
5170                 ifslastp=ifslastp->next;
5171         while (ifslastp->next != NULL) {
5172                 struct ifsregion *ifsp;
5173                 INT_OFF;
5174                 ifsp = ifslastp->next->next;
5175                 free(ifslastp->next);
5176                 ifslastp->next = ifsp;
5177                 INT_ON;
5178         }
5179         if (ifslastp->endoff > endoff)
5180                 ifslastp->endoff = endoff;
5181 }
5182
5183 static char *
5184 exptilde(char *startp, char *p, int flag)
5185 {
5186         char c;
5187         char *name;
5188         struct passwd *pw;
5189         const char *home;
5190         int quotes = flag & (EXP_FULL | EXP_CASE);
5191         int startloc;
5192
5193         name = p + 1;
5194
5195         while ((c = *++p) != '\0') {
5196                 switch (c) {
5197                 case CTLESC:
5198                         return startp;
5199                 case CTLQUOTEMARK:
5200                         return startp;
5201                 case ':':
5202                         if (flag & EXP_VARTILDE)
5203                                 goto done;
5204                         break;
5205                 case '/':
5206                 case CTLENDVAR:
5207                         goto done;
5208                 }
5209         }
5210  done:
5211         *p = '\0';
5212         if (*name == '\0') {
5213                 home = lookupvar(homestr);
5214         } else {
5215                 pw = getpwnam(name);
5216                 if (pw == NULL)
5217                         goto lose;
5218                 home = pw->pw_dir;
5219         }
5220         if (!home || !*home)
5221                 goto lose;
5222         *p = c;
5223         startloc = expdest - (char *)stackblock();
5224         strtodest(home, SQSYNTAX, quotes);
5225         recordregion(startloc, expdest - (char *)stackblock(), 0);
5226         return p;
5227  lose:
5228         *p = c;
5229         return startp;
5230 }
5231
5232 /*
5233  * Execute a command inside back quotes.  If it's a builtin command, we
5234  * want to save its output in a block obtained from malloc.  Otherwise
5235  * we fork off a subprocess and get the output of the command via a pipe.
5236  * Should be called with interrupts off.
5237  */
5238 struct backcmd {                /* result of evalbackcmd */
5239         int fd;                 /* file descriptor to read from */
5240         char *buf;              /* buffer */
5241         int nleft;              /* number of chars in buffer */
5242         struct job *jp;         /* job structure for command */
5243 };
5244
5245 /* These forward decls are needed to use "eval" code for backticks handling: */
5246 static int back_exitstatus; /* exit status of backquoted command */
5247 #define EV_EXIT 01              /* exit after evaluating tree */
5248 static void evaltree(union node *, int);
5249
5250 static void
5251 evalbackcmd(union node *n, struct backcmd *result)
5252 {
5253         int saveherefd;
5254
5255         result->fd = -1;
5256         result->buf = NULL;
5257         result->nleft = 0;
5258         result->jp = NULL;
5259         if (n == NULL) {
5260                 goto out;
5261         }
5262
5263         saveherefd = herefd;
5264         herefd = -1;
5265
5266         {
5267                 int pip[2];
5268                 struct job *jp;
5269
5270                 if (pipe(pip) < 0)
5271                         ash_msg_and_raise_error("pipe call failed");
5272                 jp = makejob(n, 1);
5273                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5274                         FORCE_INT_ON;
5275                         close(pip[0]);
5276                         if (pip[1] != 1) {
5277                                 close(1);
5278                                 copyfd(pip[1], 1);
5279                                 close(pip[1]);
5280                         }
5281                         eflag = 0;
5282                         evaltree(n, EV_EXIT); /* actually evaltreenr... */
5283                         /* NOTREACHED */
5284                 }
5285                 close(pip[1]);
5286                 result->fd = pip[0];
5287                 result->jp = jp;
5288         }
5289         herefd = saveherefd;
5290  out:
5291         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5292                 result->fd, result->buf, result->nleft, result->jp));
5293 }
5294
5295 /*
5296  * Expand stuff in backwards quotes.
5297  */
5298 static void
5299 expbackq(union node *cmd, int quoted, int quotes)
5300 {
5301         struct backcmd in;
5302         int i;
5303         char buf[128];
5304         char *p;
5305         char *dest;
5306         int startloc;
5307         int syntax = quoted? DQSYNTAX : BASESYNTAX;
5308         struct stackmark smark;
5309
5310         INT_OFF;
5311         setstackmark(&smark);
5312         dest = expdest;
5313         startloc = dest - (char *)stackblock();
5314         grabstackstr(dest);
5315         evalbackcmd(cmd, &in);
5316         popstackmark(&smark);
5317
5318         p = in.buf;
5319         i = in.nleft;
5320         if (i == 0)
5321                 goto read;
5322         for (;;) {
5323                 memtodest(p, i, syntax, quotes);
5324  read:
5325                 if (in.fd < 0)
5326                         break;
5327                 i = safe_read(in.fd, buf, sizeof(buf));
5328                 TRACE(("expbackq: read returns %d\n", i));
5329                 if (i <= 0)
5330                         break;
5331                 p = buf;
5332         }
5333
5334         free(in.buf);
5335         if (in.fd >= 0) {
5336                 close(in.fd);
5337                 back_exitstatus = waitforjob(in.jp);
5338         }
5339         INT_ON;
5340
5341         /* Eat all trailing newlines */
5342         dest = expdest;
5343         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5344                 STUNPUTC(dest);
5345         expdest = dest;
5346
5347         if (quoted == 0)
5348                 recordregion(startloc, dest - (char *)stackblock(), 0);
5349         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5350                 (dest - (char *)stackblock()) - startloc,
5351                 (dest - (char *)stackblock()) - startloc,
5352                 stackblock() + startloc));
5353 }
5354
5355 #if ENABLE_ASH_MATH_SUPPORT
5356 /*
5357  * Expand arithmetic expression.  Backup to start of expression,
5358  * evaluate, place result in (backed up) result, adjust string position.
5359  */
5360 static void
5361 expari(int quotes)
5362 {
5363         char *p, *start;
5364         int begoff;
5365         int flag;
5366         int len;
5367
5368         /*      ifsfree(); */
5369
5370         /*
5371          * This routine is slightly over-complicated for
5372          * efficiency.  Next we scan backwards looking for the
5373          * start of arithmetic.
5374          */
5375         start = stackblock();
5376         p = expdest - 1;
5377         *p = '\0';
5378         p--;
5379         do {
5380                 int esc;
5381
5382                 while (*p != CTLARI) {
5383                         p--;
5384 #if DEBUG
5385                         if (p < start) {
5386                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5387                         }
5388 #endif
5389                 }
5390
5391                 esc = esclen(start, p);
5392                 if (!(esc % 2)) {
5393                         break;
5394                 }
5395
5396                 p -= esc + 1;
5397         } while (1);
5398
5399         begoff = p - start;
5400
5401         removerecordregions(begoff);
5402
5403         flag = p[1];
5404
5405         expdest = p;
5406
5407         if (quotes)
5408                 rmescapes(p + 2);
5409
5410         len = cvtnum(dash_arith(p + 2));
5411
5412         if (flag != '"')
5413                 recordregion(begoff, begoff + len, 0);
5414 }
5415 #endif
5416
5417 /* argstr needs it */
5418 static char *evalvar(char *p, int flag);
5419
5420 /*
5421  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
5422  * characters to allow for further processing.  Otherwise treat
5423  * $@ like $* since no splitting will be performed.
5424  */
5425 static void
5426 argstr(char *p, int flag)
5427 {
5428         static const char spclchars[] ALIGN1 = {
5429                 '=',
5430                 ':',
5431                 CTLQUOTEMARK,
5432                 CTLENDVAR,
5433                 CTLESC,
5434                 CTLVAR,
5435                 CTLBACKQ,
5436                 CTLBACKQ | CTLQUOTE,
5437 #if ENABLE_ASH_MATH_SUPPORT
5438                 CTLENDARI,
5439 #endif
5440                 0
5441         };
5442         const char *reject = spclchars;
5443         int c;
5444         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
5445         int breakall = flag & EXP_WORD;
5446         int inquotes;
5447         size_t length;
5448         int startloc;
5449
5450         if (!(flag & EXP_VARTILDE)) {
5451                 reject += 2;
5452         } else if (flag & EXP_VARTILDE2) {
5453                 reject++;
5454         }
5455         inquotes = 0;
5456         length = 0;
5457         if (flag & EXP_TILDE) {
5458                 char *q;
5459
5460                 flag &= ~EXP_TILDE;
5461  tilde:
5462                 q = p;
5463                 if (*q == CTLESC && (flag & EXP_QWORD))
5464                         q++;
5465                 if (*q == '~')
5466                         p = exptilde(p, q, flag);
5467         }
5468  start:
5469         startloc = expdest - (char *)stackblock();
5470         for (;;) {
5471                 length += strcspn(p + length, reject);
5472                 c = p[length];
5473                 if (c && (!(c & 0x80)
5474 #if ENABLE_ASH_MATH_SUPPORT
5475                                         || c == CTLENDARI
5476 #endif
5477                    )) {
5478                         /* c == '=' || c == ':' || c == CTLENDARI */
5479                         length++;
5480                 }
5481                 if (length > 0) {
5482                         int newloc;
5483                         expdest = stack_nputstr(p, length, expdest);
5484                         newloc = expdest - (char *)stackblock();
5485                         if (breakall && !inquotes && newloc > startloc) {
5486                                 recordregion(startloc, newloc, 0);
5487                         }
5488                         startloc = newloc;
5489                 }
5490                 p += length + 1;
5491                 length = 0;
5492
5493                 switch (c) {
5494                 case '\0':
5495                         goto breakloop;
5496                 case '=':
5497                         if (flag & EXP_VARTILDE2) {
5498                                 p--;
5499                                 continue;
5500                         }
5501                         flag |= EXP_VARTILDE2;
5502                         reject++;
5503                         /* fall through */
5504                 case ':':
5505                         /*
5506                          * sort of a hack - expand tildes in variable
5507                          * assignments (after the first '=' and after ':'s).
5508                          */
5509                         if (*--p == '~') {
5510                                 goto tilde;
5511                         }
5512                         continue;
5513                 }
5514
5515                 switch (c) {
5516                 case CTLENDVAR: /* ??? */
5517                         goto breakloop;
5518                 case CTLQUOTEMARK:
5519                         /* "$@" syntax adherence hack */
5520                         if (
5521                                 !inquotes &&
5522                                 !memcmp(p, dolatstr, 4) &&
5523                                 (p[4] == CTLQUOTEMARK || (
5524                                         p[4] == CTLENDVAR &&
5525                                         p[5] == CTLQUOTEMARK
5526                                 ))
5527                         ) {
5528                                 p = evalvar(p + 1, flag) + 1;
5529                                 goto start;
5530                         }
5531                         inquotes = !inquotes;
5532  addquote:
5533                         if (quotes) {
5534                                 p--;
5535                                 length++;
5536                                 startloc++;
5537                         }
5538                         break;
5539                 case CTLESC:
5540                         startloc++;
5541                         length++;
5542                         goto addquote;
5543                 case CTLVAR:
5544                         p = evalvar(p, flag);
5545                         goto start;
5546                 case CTLBACKQ:
5547                         c = 0;
5548                 case CTLBACKQ|CTLQUOTE:
5549                         expbackq(argbackq->n, c, quotes);
5550                         argbackq = argbackq->next;
5551                         goto start;
5552 #if ENABLE_ASH_MATH_SUPPORT
5553                 case CTLENDARI:
5554                         p--;
5555                         expari(quotes);
5556                         goto start;
5557 #endif
5558                 }
5559         }
5560  breakloop:
5561         ;
5562 }
5563
5564 static char *
5565 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5566         int zero)
5567 {
5568         char *loc;
5569         char *loc2;
5570         char c;
5571
5572         loc = startp;
5573         loc2 = rmesc;
5574         do {
5575                 int match;
5576                 const char *s = loc2;
5577                 c = *loc2;
5578                 if (zero) {
5579                         *loc2 = '\0';
5580                         s = rmesc;
5581                 }
5582                 match = pmatch(str, s);
5583                 *loc2 = c;
5584                 if (match)
5585                         return loc;
5586                 if (quotes && *loc == CTLESC)
5587                         loc++;
5588                 loc++;
5589                 loc2++;
5590         } while (c);
5591         return 0;
5592 }
5593
5594 static char *
5595 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5596         int zero)
5597 {
5598         int esc = 0;
5599         char *loc;
5600         char *loc2;
5601
5602         for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5603                 int match;
5604                 char c = *loc2;
5605                 const char *s = loc2;
5606                 if (zero) {
5607                         *loc2 = '\0';
5608                         s = rmesc;
5609                 }
5610                 match = pmatch(str, s);
5611                 *loc2 = c;
5612                 if (match)
5613                         return loc;
5614                 loc--;
5615                 if (quotes) {
5616                         if (--esc < 0) {
5617                                 esc = esclen(startp, loc);
5618                         }
5619                         if (esc % 2) {
5620                                 esc--;
5621                                 loc--;
5622                         }
5623                 }
5624         }
5625         return 0;
5626 }
5627
5628 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5629 static void
5630 varunset(const char *end, const char *var, const char *umsg, int varflags)
5631 {
5632         const char *msg;
5633         const char *tail;
5634
5635         tail = nullstr;
5636         msg = "parameter not set";
5637         if (umsg) {
5638                 if (*end == CTLENDVAR) {
5639                         if (varflags & VSNUL)
5640                                 tail = " or null";
5641                 } else
5642                         msg = umsg;
5643         }
5644         ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5645 }
5646
5647 static const char *
5648 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5649 {
5650         char *startp;
5651         char *loc;
5652         int saveherefd = herefd;
5653         struct nodelist *saveargbackq = argbackq;
5654         int amount;
5655         char *rmesc, *rmescend;
5656         int zero;
5657         char *(*scan)(char *, char *, char *, char *, int , int);
5658
5659         herefd = -1;
5660         argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5661         STPUTC('\0', expdest);
5662         herefd = saveherefd;
5663         argbackq = saveargbackq;
5664         startp = stackblock() + startloc;
5665
5666         switch (subtype) {
5667         case VSASSIGN:
5668                 setvar(str, startp, 0);
5669                 amount = startp - expdest;
5670                 STADJUST(amount, expdest);
5671                 return startp;
5672
5673         case VSQUESTION:
5674                 varunset(p, str, startp, varflags);
5675                 /* NOTREACHED */
5676         }
5677
5678         subtype -= VSTRIMRIGHT;
5679 #if DEBUG
5680         if (subtype < 0 || subtype > 3)
5681                 abort();
5682 #endif
5683
5684         rmesc = startp;
5685         rmescend = stackblock() + strloc;
5686         if (quotes) {
5687                 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5688                 if (rmesc != startp) {
5689                         rmescend = expdest;
5690                         startp = stackblock() + startloc;
5691                 }
5692         }
5693         rmescend--;
5694         str = stackblock() + strloc;
5695         preglob(str, varflags & VSQUOTE, 0);
5696
5697         /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5698         zero = subtype >> 1;
5699         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5700         scan = (subtype & 1) ^ zero ? scanleft : scanright;
5701
5702         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5703         if (loc) {
5704                 if (zero) {
5705                         memmove(startp, loc, str - loc);
5706                         loc = startp + (str - loc) - 1;
5707                 }
5708                 *loc = '\0';
5709                 amount = loc - expdest;
5710                 STADJUST(amount, expdest);
5711         }
5712         return loc;
5713 }
5714
5715 /*
5716  * Add the value of a specialized variable to the stack string.
5717  */
5718 static ssize_t
5719 varvalue(char *name, int varflags, int flags)
5720 {
5721         int num;
5722         char *p;
5723         int i;
5724         int sep = 0;
5725         int sepq = 0;
5726         ssize_t len = 0;
5727         char **ap;
5728         int syntax;
5729         int quoted = varflags & VSQUOTE;
5730         int subtype = varflags & VSTYPE;
5731         int quotes = flags & (EXP_FULL | EXP_CASE);
5732
5733         if (quoted && (flags & EXP_FULL))
5734                 sep = 1 << CHAR_BIT;
5735
5736         syntax = quoted ? DQSYNTAX : BASESYNTAX;
5737         switch (*name) {
5738         case '$':
5739                 num = rootpid;
5740                 goto numvar;
5741         case '?':
5742                 num = exitstatus;
5743                 goto numvar;
5744         case '#':
5745                 num = shellparam.nparam;
5746                 goto numvar;
5747         case '!':
5748                 num = backgndpid;
5749                 if (num == 0)
5750                         return -1;
5751  numvar:
5752                 len = cvtnum(num);
5753                 break;
5754         case '-':
5755                 p = makestrspace(NOPTS, expdest);
5756                 for (i = NOPTS - 1; i >= 0; i--) {
5757                         if (optlist[i]) {
5758                                 USTPUTC(optletters(i), p);
5759                                 len++;
5760                         }
5761                 }
5762                 expdest = p;
5763                 break;
5764         case '@':
5765                 if (sep)
5766                         goto param;
5767                 /* fall through */
5768         case '*':
5769                 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
5770                 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5771                         sepq = 1;
5772  param:
5773                 ap = shellparam.p;
5774                 if (!ap)
5775                         return -1;
5776                 while ((p = *ap++)) {
5777                         size_t partlen;
5778
5779                         partlen = strlen(p);
5780                         len += partlen;
5781
5782                         if (!(subtype == VSPLUS || subtype == VSLENGTH))
5783                                 memtodest(p, partlen, syntax, quotes);
5784
5785                         if (*ap && sep) {
5786                                 char *q;
5787
5788                                 len++;
5789                                 if (subtype == VSPLUS || subtype == VSLENGTH) {
5790                                         continue;
5791                                 }
5792                                 q = expdest;
5793                                 if (sepq)
5794                                         STPUTC(CTLESC, q);
5795                                 STPUTC(sep, q);
5796                                 expdest = q;
5797                         }
5798                 }
5799                 return len;
5800         case '0':
5801         case '1':
5802         case '2':
5803         case '3':
5804         case '4':
5805         case '5':
5806         case '6':
5807         case '7':
5808         case '8':
5809         case '9':
5810                 num = atoi(name);
5811                 if (num < 0 || num > shellparam.nparam)
5812                         return -1;
5813                 p = num ? shellparam.p[num - 1] : arg0;
5814                 goto value;
5815         default:
5816                 p = lookupvar(name);
5817  value:
5818                 if (!p)
5819                         return -1;
5820
5821                 len = strlen(p);
5822                 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5823                         memtodest(p, len, syntax, quotes);
5824                 return len;
5825         }
5826
5827         if (subtype == VSPLUS || subtype == VSLENGTH)
5828                 STADJUST(-len, expdest);
5829         return len;
5830 }
5831
5832 /*
5833  * Expand a variable, and return a pointer to the next character in the
5834  * input string.
5835  */
5836 static char *
5837 evalvar(char *p, int flag)
5838 {
5839         int subtype;
5840         int varflags;
5841         char *var;
5842         int patloc;
5843         int c;
5844         int startloc;
5845         ssize_t varlen;
5846         int easy;
5847         int quotes;
5848         int quoted;
5849
5850         quotes = flag & (EXP_FULL | EXP_CASE);
5851         varflags = *p++;
5852         subtype = varflags & VSTYPE;
5853         quoted = varflags & VSQUOTE;
5854         var = p;
5855         easy = (!quoted || (*var == '@' && shellparam.nparam));
5856         startloc = expdest - (char *)stackblock();
5857         p = strchr(p, '=') + 1;
5858
5859  again:
5860         varlen = varvalue(var, varflags, flag);
5861         if (varflags & VSNUL)
5862                 varlen--;
5863
5864         if (subtype == VSPLUS) {
5865                 varlen = -1 - varlen;
5866                 goto vsplus;
5867         }
5868
5869         if (subtype == VSMINUS) {
5870  vsplus:
5871                 if (varlen < 0) {
5872                         argstr(
5873                                 p, flag | EXP_TILDE |
5874                                         (quoted ?  EXP_QWORD : EXP_WORD)
5875                         );
5876                         goto end;
5877                 }
5878                 if (easy)
5879                         goto record;
5880                 goto end;
5881         }
5882
5883         if (subtype == VSASSIGN || subtype == VSQUESTION) {
5884                 if (varlen < 0) {
5885                         if (subevalvar(p, var, 0, subtype, startloc, varflags, 0)) {
5886                                 varflags &= ~VSNUL;
5887                                 /*
5888                                  * Remove any recorded regions beyond
5889                                  * start of variable
5890                                  */
5891                                 removerecordregions(startloc);
5892                                 goto again;
5893                         }
5894                         goto end;
5895                 }
5896                 if (easy)
5897                         goto record;
5898                 goto end;
5899         }
5900
5901         if (varlen < 0 && uflag)
5902                 varunset(p, var, 0, 0);
5903
5904         if (subtype == VSLENGTH) {
5905                 cvtnum(varlen > 0 ? varlen : 0);
5906                 goto record;
5907         }
5908
5909         if (subtype == VSNORMAL) {
5910                 if (!easy)
5911                         goto end;
5912  record:
5913                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5914                 goto end;
5915         }
5916
5917 #if DEBUG
5918         switch (subtype) {
5919         case VSTRIMLEFT:
5920         case VSTRIMLEFTMAX:
5921         case VSTRIMRIGHT:
5922         case VSTRIMRIGHTMAX:
5923                 break;
5924         default:
5925                 abort();
5926         }
5927 #endif
5928
5929         if (varlen >= 0) {
5930                 /*
5931                  * Terminate the string and start recording the pattern
5932                  * right after it
5933                  */
5934                 STPUTC('\0', expdest);
5935                 patloc = expdest - (char *)stackblock();
5936                 if (subevalvar(p, NULL, patloc, subtype,
5937                                 startloc, varflags, quotes) == 0) {
5938                         int amount = expdest - (
5939                                 (char *)stackblock() + patloc - 1
5940                         );
5941                         STADJUST(-amount, expdest);
5942                 }
5943                 /* Remove any recorded regions beyond start of variable */
5944                 removerecordregions(startloc);
5945                 goto record;
5946         }
5947
5948  end:
5949         if (subtype != VSNORMAL) {      /* skip to end of alternative */
5950                 int nesting = 1;
5951                 for (;;) {
5952                         c = *p++;
5953                         if (c == CTLESC)
5954                                 p++;
5955                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5956                                 if (varlen >= 0)
5957                                         argbackq = argbackq->next;
5958                         } else if (c == CTLVAR) {
5959                                 if ((*p++ & VSTYPE) != VSNORMAL)
5960                                         nesting++;
5961                         } else if (c == CTLENDVAR) {
5962                                 if (--nesting == 0)
5963                                         break;
5964                         }
5965                 }
5966         }
5967         return p;
5968 }
5969
5970 /*
5971  * Break the argument string into pieces based upon IFS and add the
5972  * strings to the argument list.  The regions of the string to be
5973  * searched for IFS characters have been stored by recordregion.
5974  */
5975 static void
5976 ifsbreakup(char *string, struct arglist *arglist)
5977 {
5978         struct ifsregion *ifsp;
5979         struct strlist *sp;
5980         char *start;
5981         char *p;
5982         char *q;
5983         const char *ifs, *realifs;
5984         int ifsspc;
5985         int nulonly;
5986
5987         start = string;
5988         if (ifslastp != NULL) {
5989                 ifsspc = 0;
5990                 nulonly = 0;
5991                 realifs = ifsset() ? ifsval() : defifs;
5992                 ifsp = &ifsfirst;
5993                 do {
5994                         p = string + ifsp->begoff;
5995                         nulonly = ifsp->nulonly;
5996                         ifs = nulonly ? nullstr : realifs;
5997                         ifsspc = 0;
5998                         while (p < string + ifsp->endoff) {
5999                                 q = p;
6000                                 if (*p == CTLESC)
6001                                         p++;
6002                                 if (!strchr(ifs, *p)) {
6003                                         p++;
6004                                         continue;
6005                                 }
6006                                 if (!nulonly)
6007                                         ifsspc = (strchr(defifs, *p) != NULL);
6008                                 /* Ignore IFS whitespace at start */
6009                                 if (q == start && ifsspc) {
6010                                         p++;
6011                                         start = p;
6012                                         continue;
6013                                 }
6014                                 *q = '\0';
6015                                 sp = stalloc(sizeof(*sp));
6016                                 sp->text = start;
6017                                 *arglist->lastp = sp;
6018                                 arglist->lastp = &sp->next;
6019                                 p++;
6020                                 if (!nulonly) {
6021                                         for (;;) {
6022                                                 if (p >= string + ifsp->endoff) {
6023                                                         break;
6024                                                 }
6025                                                 q = p;
6026                                                 if (*p == CTLESC)
6027                                                         p++;
6028                                                 if (strchr(ifs, *p) == NULL ) {
6029                                                         p = q;
6030                                                         break;
6031                                                 } else if (strchr(defifs, *p) == NULL) {
6032                                                         if (ifsspc) {
6033                                                                 p++;
6034                                                                 ifsspc = 0;
6035                                                         } else {
6036                                                                 p = q;
6037                                                                 break;
6038                                                         }
6039                                                 } else
6040                                                         p++;
6041                                         }
6042                                 }
6043                                 start = p;
6044                         } /* while */
6045                         ifsp = ifsp->next;
6046                 } while (ifsp != NULL);
6047                 if (nulonly)
6048                         goto add;
6049         }
6050
6051         if (!*start)
6052                 return;
6053
6054  add:
6055         sp = stalloc(sizeof(*sp));
6056         sp->text = start;
6057         *arglist->lastp = sp;
6058         arglist->lastp = &sp->next;
6059 }
6060
6061 static void
6062 ifsfree(void)
6063 {
6064         struct ifsregion *p;
6065
6066         INT_OFF;
6067         p = ifsfirst.next;
6068         do {
6069                 struct ifsregion *ifsp;
6070                 ifsp = p->next;
6071                 free(p);
6072                 p = ifsp;
6073         } while (p);
6074         ifslastp = NULL;
6075         ifsfirst.next = NULL;
6076         INT_ON;
6077 }
6078
6079 /*
6080  * Add a file name to the list.
6081  */
6082 static void
6083 addfname(const char *name)
6084 {
6085         struct strlist *sp;
6086
6087         sp = stalloc(sizeof(*sp));
6088         sp->text = ststrdup(name);
6089         *exparg.lastp = sp;
6090         exparg.lastp = &sp->next;
6091 }
6092
6093 static char *expdir;
6094
6095 /*
6096  * Do metacharacter (i.e. *, ?, [...]) expansion.
6097  */
6098 static void
6099 expmeta(char *enddir, char *name)
6100 {
6101         char *p;
6102         const char *cp;
6103         char *start;
6104         char *endname;
6105         int metaflag;
6106         struct stat statb;
6107         DIR *dirp;
6108         struct dirent *dp;
6109         int atend;
6110         int matchdot;
6111
6112         metaflag = 0;
6113         start = name;
6114         for (p = name; *p; p++) {
6115                 if (*p == '*' || *p == '?')
6116                         metaflag = 1;
6117                 else if (*p == '[') {
6118                         char *q = p + 1;
6119                         if (*q == '!')
6120                                 q++;
6121                         for (;;) {
6122                                 if (*q == '\\')
6123                                         q++;
6124                                 if (*q == '/' || *q == '\0')
6125                                         break;
6126                                 if (*++q == ']') {
6127                                         metaflag = 1;
6128                                         break;
6129                                 }
6130                         }
6131                 } else if (*p == '\\')
6132                         p++;
6133                 else if (*p == '/') {
6134                         if (metaflag)
6135                                 goto out;
6136                         start = p + 1;
6137                 }
6138         }
6139  out:
6140         if (metaflag == 0) {    /* we've reached the end of the file name */
6141                 if (enddir != expdir)
6142                         metaflag++;
6143                 p = name;
6144                 do {
6145                         if (*p == '\\')
6146                                 p++;
6147                         *enddir++ = *p;
6148                 } while (*p++);
6149                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6150                         addfname(expdir);
6151                 return;
6152         }
6153         endname = p;
6154         if (name < start) {
6155                 p = name;
6156                 do {
6157                         if (*p == '\\')
6158                                 p++;
6159                         *enddir++ = *p++;
6160                 } while (p < start);
6161         }
6162         if (enddir == expdir) {
6163                 cp = ".";
6164         } else if (enddir == expdir + 1 && *expdir == '/') {
6165                 cp = "/";
6166         } else {
6167                 cp = expdir;
6168                 enddir[-1] = '\0';
6169         }
6170         dirp = opendir(cp);
6171         if (dirp == NULL)
6172                 return;
6173         if (enddir != expdir)
6174                 enddir[-1] = '/';
6175         if (*endname == 0) {
6176                 atend = 1;
6177         } else {
6178                 atend = 0;
6179                 *endname++ = '\0';
6180         }
6181         matchdot = 0;
6182         p = start;
6183         if (*p == '\\')
6184                 p++;
6185         if (*p == '.')
6186                 matchdot++;
6187         while (! intpending && (dp = readdir(dirp)) != NULL) {
6188                 if (dp->d_name[0] == '.' && ! matchdot)
6189                         continue;
6190                 if (pmatch(start, dp->d_name)) {
6191                         if (atend) {
6192                                 strcpy(enddir, dp->d_name);
6193                                 addfname(expdir);
6194                         } else {
6195                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6196                                         continue;
6197                                 p[-1] = '/';
6198                                 expmeta(p, endname);
6199                         }
6200                 }
6201         }
6202         closedir(dirp);
6203         if (! atend)
6204                 endname[-1] = '/';
6205 }
6206
6207 static struct strlist *
6208 msort(struct strlist *list, int len)
6209 {
6210         struct strlist *p, *q = NULL;
6211         struct strlist **lpp;
6212         int half;
6213         int n;
6214
6215         if (len <= 1)
6216                 return list;
6217         half = len >> 1;
6218         p = list;
6219         for (n = half; --n >= 0; ) {
6220                 q = p;
6221                 p = p->next;
6222         }
6223         q->next = NULL;                 /* terminate first half of list */
6224         q = msort(list, half);          /* sort first half of list */
6225         p = msort(p, len - half);               /* sort second half */
6226         lpp = &list;
6227         for (;;) {
6228 #if ENABLE_LOCALE_SUPPORT
6229                 if (strcoll(p->text, q->text) < 0)
6230 #else
6231                 if (strcmp(p->text, q->text) < 0)
6232 #endif
6233                                                 {
6234                         *lpp = p;
6235                         lpp = &p->next;
6236                         p = *lpp;
6237                         if (p == NULL) {
6238                                 *lpp = q;
6239                                 break;
6240                         }
6241                 } else {
6242                         *lpp = q;
6243                         lpp = &q->next;
6244                         q = *lpp;
6245                         if (q == NULL) {
6246                                 *lpp = p;
6247                                 break;
6248                         }
6249                 }
6250         }
6251         return list;
6252 }
6253
6254 /*
6255  * Sort the results of file name expansion.  It calculates the number of
6256  * strings to sort and then calls msort (short for merge sort) to do the
6257  * work.
6258  */
6259 static struct strlist *
6260 expsort(struct strlist *str)
6261 {
6262         int len;
6263         struct strlist *sp;
6264
6265         len = 0;
6266         for (sp = str; sp; sp = sp->next)
6267                 len++;
6268         return msort(str, len);
6269 }
6270
6271 static void
6272 expandmeta(struct strlist *str, int flag)
6273 {
6274         static const char metachars[] ALIGN1 = {
6275                 '*', '?', '[', 0
6276         };
6277         /* TODO - EXP_REDIR */
6278
6279         while (str) {
6280                 struct strlist **savelastp;
6281                 struct strlist *sp;
6282                 char *p;
6283
6284                 if (fflag)
6285                         goto nometa;
6286                 if (!strpbrk(str->text, metachars))
6287                         goto nometa;
6288                 savelastp = exparg.lastp;
6289
6290                 INT_OFF;
6291                 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6292                 {
6293                         int i = strlen(str->text);
6294                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6295                 }
6296
6297                 expmeta(expdir, p);
6298                 free(expdir);
6299                 if (p != str->text)
6300                         free(p);
6301                 INT_ON;
6302                 if (exparg.lastp == savelastp) {
6303                         /*
6304                          * no matches
6305                          */
6306  nometa:
6307                         *exparg.lastp = str;
6308                         rmescapes(str->text);
6309                         exparg.lastp = &str->next;
6310                 } else {
6311                         *exparg.lastp = NULL;
6312                         *savelastp = sp = expsort(*savelastp);
6313                         while (sp->next != NULL)
6314                                 sp = sp->next;
6315                         exparg.lastp = &sp->next;
6316                 }
6317                 str = str->next;
6318         }
6319 }
6320
6321 /*
6322  * Perform variable substitution and command substitution on an argument,
6323  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
6324  * perform splitting and file name expansion.  When arglist is NULL, perform
6325  * here document expansion.
6326  */
6327 static void
6328 expandarg(union node *arg, struct arglist *arglist, int flag)
6329 {
6330         struct strlist *sp;
6331         char *p;
6332
6333         argbackq = arg->narg.backquote;
6334         STARTSTACKSTR(expdest);
6335         ifsfirst.next = NULL;
6336         ifslastp = NULL;
6337         argstr(arg->narg.text, flag);
6338         p = _STPUTC('\0', expdest);
6339         expdest = p - 1;
6340         if (arglist == NULL) {
6341                 return;                 /* here document expanded */
6342         }
6343         p = grabstackstr(p);
6344         exparg.lastp = &exparg.list;
6345         /*
6346          * TODO - EXP_REDIR
6347          */
6348         if (flag & EXP_FULL) {
6349                 ifsbreakup(p, &exparg);
6350                 *exparg.lastp = NULL;
6351                 exparg.lastp = &exparg.list;
6352                 expandmeta(exparg.list, flag);
6353         } else {
6354                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6355                         rmescapes(p);
6356                 sp = stalloc(sizeof(*sp));
6357                 sp->text = p;
6358                 *exparg.lastp = sp;
6359                 exparg.lastp = &sp->next;
6360         }
6361         if (ifsfirst.next)
6362                 ifsfree();
6363         *exparg.lastp = NULL;
6364         if (exparg.list) {
6365                 *arglist->lastp = exparg.list;
6366                 arglist->lastp = exparg.lastp;
6367         }
6368 }
6369
6370 /*
6371  * Expand shell variables and backquotes inside a here document.
6372  */
6373 static void
6374 expandhere(union node *arg, int fd)
6375 {
6376         herefd = fd;
6377         expandarg(arg, (struct arglist *)NULL, 0);
6378         full_write(fd, stackblock(), expdest - (char *)stackblock());
6379 }
6380
6381 /*
6382  * Returns true if the pattern matches the string.
6383  */
6384 static int
6385 patmatch(char *pattern, const char *string)
6386 {
6387         return pmatch(preglob(pattern, 0, 0), string);
6388 }
6389
6390 /*
6391  * See if a pattern matches in a case statement.
6392  */
6393 static int
6394 casematch(union node *pattern, char *val)
6395 {
6396         struct stackmark smark;
6397         int result;
6398
6399         setstackmark(&smark);
6400         argbackq = pattern->narg.backquote;
6401         STARTSTACKSTR(expdest);
6402         ifslastp = NULL;
6403         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6404         STACKSTRNUL(expdest);
6405         result = patmatch(stackblock(), val);
6406         popstackmark(&smark);
6407         return result;
6408 }
6409
6410
6411 /* ============ find_command */
6412
6413 struct builtincmd {
6414         const char *name;
6415         int (*builtin)(int, char **);
6416         /* unsigned flags; */
6417 };
6418 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6419 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6420 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6421
6422 struct cmdentry {
6423         int cmdtype;
6424         union param {
6425                 int index;
6426                 const struct builtincmd *cmd;
6427                 struct funcnode *func;
6428         } u;
6429 };
6430 /* values of cmdtype */
6431 #define CMDUNKNOWN      -1      /* no entry in table for command */
6432 #define CMDNORMAL       0       /* command is an executable program */
6433 #define CMDFUNCTION     1       /* command is a shell function */
6434 #define CMDBUILTIN      2       /* command is a shell builtin */
6435
6436 /* action to find_command() */
6437 #define DO_ERR          0x01    /* prints errors */
6438 #define DO_ABS          0x02    /* checks absolute paths */
6439 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
6440 #define DO_ALTPATH      0x08    /* using alternate path */
6441 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
6442
6443 static void find_command(char *, struct cmdentry *, int, const char *);
6444
6445
6446 /* ============ Hashing commands */
6447
6448 /*
6449  * When commands are first encountered, they are entered in a hash table.
6450  * This ensures that a full path search will not have to be done for them
6451  * on each invocation.
6452  *
6453  * We should investigate converting to a linear search, even though that
6454  * would make the command name "hash" a misnomer.
6455  */
6456
6457 #define CMDTABLESIZE 31         /* should be prime */
6458 #define ARB 1                   /* actual size determined at run time */
6459
6460 struct tblentry {
6461         struct tblentry *next;  /* next entry in hash chain */
6462         union param param;      /* definition of builtin function */
6463         short cmdtype;          /* index identifying command */
6464         char rehash;            /* if set, cd done since entry created */
6465         char cmdname[ARB];      /* name of command */
6466 };
6467
6468 static struct tblentry *cmdtable[CMDTABLESIZE];
6469 static int builtinloc = -1;             /* index in path of %builtin, or -1 */
6470
6471 static void
6472 tryexec(char *cmd, char **argv, char **envp)
6473 {
6474         int repeated = 0;
6475
6476 #if ENABLE_FEATURE_SH_STANDALONE
6477         if (strchr(cmd, '/') == NULL) {
6478                 const struct bb_applet *a;
6479
6480                 a = find_applet_by_name(cmd);
6481                 if (a) {
6482                         if (a->noexec)
6483                                 run_appletstruct_and_exit(a, argv);
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                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8250
8251                 sp = varlist.list;
8252                 for (n = 0; n < 2; n++) {
8253                         while (sp) {
8254                                 fdprintf(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         free(pf->buf);
8792         while (pf->strpush)
8793                 popstring();
8794         parsefile = pf->prev;
8795         free(pf);
8796         parsenleft = parsefile->nleft;
8797         parselleft = parsefile->lleft;
8798         parsenextc = parsefile->nextc;
8799         plinno = parsefile->linno;
8800         INT_ON;
8801 }
8802
8803 /*
8804  * Return to top level.
8805  */
8806 static void
8807 popallfiles(void)
8808 {
8809         while (parsefile != &basepf)
8810                 popfile();
8811 }
8812
8813 /*
8814  * Close the file(s) that the shell is reading commands from.  Called
8815  * after a fork is done.
8816  */
8817 static void
8818 closescript(void)
8819 {
8820         popallfiles();
8821         if (parsefile->fd > 0) {
8822                 close(parsefile->fd);
8823                 parsefile->fd = 0;
8824         }
8825 }
8826
8827 /*
8828  * Like setinputfile, but takes an open file descriptor.  Call this with
8829  * interrupts off.
8830  */
8831 static void
8832 setinputfd(int fd, int push)
8833 {
8834         close_on_exec_on(fd);
8835         if (push) {
8836                 pushfile();
8837                 parsefile->buf = 0;
8838         }
8839         parsefile->fd = fd;
8840         if (parsefile->buf == NULL)
8841                 parsefile->buf = ckmalloc(IBUFSIZ);
8842         parselleft = parsenleft = 0;
8843         plinno = 1;
8844 }
8845
8846 /*
8847  * Set the input to take input from a file.  If push is set, push the
8848  * old input onto the stack first.
8849  */
8850 static int
8851 setinputfile(const char *fname, int flags)
8852 {
8853         int fd;
8854         int fd2;
8855
8856         INT_OFF;
8857         fd = open(fname, O_RDONLY);
8858         if (fd < 0) {
8859                 if (flags & INPUT_NOFILE_OK)
8860                         goto out;
8861                 ash_msg_and_raise_error("can't open %s", fname);
8862         }
8863         if (fd < 10) {
8864                 fd2 = copyfd(fd, 10);
8865                 close(fd);
8866                 if (fd2 < 0)
8867                         ash_msg_and_raise_error("out of file descriptors");
8868                 fd = fd2;
8869         }
8870         setinputfd(fd, flags & INPUT_PUSH_FILE);
8871  out:
8872         INT_ON;
8873         return fd;
8874 }
8875
8876 /*
8877  * Like setinputfile, but takes input from a string.
8878  */
8879 static void
8880 setinputstring(char *string)
8881 {
8882         INT_OFF;
8883         pushfile();
8884         parsenextc = string;
8885         parsenleft = strlen(string);
8886         parsefile->buf = NULL;
8887         plinno = 1;
8888         INT_ON;
8889 }
8890
8891
8892 /* ============ mail.c
8893  *
8894  * Routines to check for mail.
8895  */
8896
8897 #if ENABLE_ASH_MAIL
8898
8899 #define MAXMBOXES 10
8900
8901 /* times of mailboxes */
8902 static time_t mailtime[MAXMBOXES];
8903 /* Set if MAIL or MAILPATH is changed. */
8904 static smallint mail_var_path_changed;
8905
8906 /*
8907  * Print appropriate message(s) if mail has arrived.
8908  * If mail_var_path_changed is set,
8909  * then the value of MAIL has mail_var_path_changed,
8910  * so we just update the values.
8911  */
8912 static void
8913 chkmail(void)
8914 {
8915         const char *mpath;
8916         char *p;
8917         char *q;
8918         time_t *mtp;
8919         struct stackmark smark;
8920         struct stat statb;
8921
8922         setstackmark(&smark);
8923         mpath = mpathset() ? mpathval() : mailval();
8924         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8925                 p = padvance(&mpath, nullstr);
8926                 if (p == NULL)
8927                         break;
8928                 if (*p == '\0')
8929                         continue;
8930                 for (q = p; *q; q++);
8931 #if DEBUG
8932                 if (q[-1] != '/')
8933                         abort();
8934 #endif
8935                 q[-1] = '\0';                   /* delete trailing '/' */
8936                 if (stat(p, &statb) < 0) {
8937                         *mtp = 0;
8938                         continue;
8939                 }
8940                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8941                         fprintf(
8942                                 stderr, snlfmt,
8943                                 pathopt ? pathopt : "you have mail"
8944                         );
8945                 }
8946                 *mtp = statb.st_mtime;
8947         }
8948         mail_var_path_changed = 0;
8949         popstackmark(&smark);
8950 }
8951
8952 static void
8953 changemail(const char *val)
8954 {
8955         mail_var_path_changed = 1;
8956 }
8957
8958 #endif /* ASH_MAIL */
8959
8960
8961 /* ============ ??? */
8962
8963 /*
8964  * Set the shell parameters.
8965  */
8966 static void
8967 setparam(char **argv)
8968 {
8969         char **newparam;
8970         char **ap;
8971         int nparam;
8972
8973         for (nparam = 0; argv[nparam]; nparam++);
8974         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8975         while (*argv) {
8976                 *ap++ = ckstrdup(*argv++);
8977         }
8978         *ap = NULL;
8979         freeparam(&shellparam);
8980         shellparam.malloc = 1;
8981         shellparam.nparam = nparam;
8982         shellparam.p = newparam;
8983 #if ENABLE_ASH_GETOPTS
8984         shellparam.optind = 1;
8985         shellparam.optoff = -1;
8986 #endif
8987 }
8988
8989 /*
8990  * Process shell options.  The global variable argptr contains a pointer
8991  * to the argument list; we advance it past the options.
8992  */
8993 static void
8994 minus_o(char *name, int val)
8995 {
8996         int i;
8997
8998         if (name) {
8999                 for (i = 0; i < NOPTS; i++) {
9000                         if (strcmp(name, optnames(i)) == 0) {
9001                                 optlist[i] = val;
9002                                 return;
9003                         }
9004                 }
9005                 ash_msg_and_raise_error("illegal option -o %s", name);
9006         }
9007         out1str("Current option settings\n");
9008         for (i = 0; i < NOPTS; i++)
9009                 out1fmt("%-16s%s\n", optnames(i),
9010                                 optlist[i] ? "on" : "off");
9011 }
9012 static void
9013 setoption(int flag, int val)
9014 {
9015         int i;
9016
9017         for (i = 0; i < NOPTS; i++) {
9018                 if (optletters(i) == flag) {
9019                         optlist[i] = val;
9020                         return;
9021                 }
9022         }
9023         ash_msg_and_raise_error("illegal option -%c", flag);
9024         /* NOTREACHED */
9025 }
9026 static void
9027 options(int cmdline)
9028 {
9029         char *p;
9030         int val;
9031         int c;
9032
9033         if (cmdline)
9034                 minusc = NULL;
9035         while ((p = *argptr) != NULL) {
9036                 c = *p++;
9037                 if (c != '-' && c != '+')
9038                         break;
9039                 argptr++;
9040                 val = 0; /* val = 0 if c == '+' */
9041                 if (c == '-') {
9042                         val = 1;
9043                         if (p[0] == '\0' || LONE_DASH(p)) {
9044                                 if (!cmdline) {
9045                                         /* "-" means turn off -x and -v */
9046                                         if (p[0] == '\0')
9047                                                 xflag = vflag = 0;
9048                                         /* "--" means reset params */
9049                                         else if (*argptr == NULL)
9050                                                 setparam(argptr);
9051                                 }
9052                                 break;    /* "-" or  "--" terminates options */
9053                         }
9054                 }
9055                 /* first char was + or - */
9056                 while ((c = *p++) != '\0') {
9057                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9058                         if (c == 'c' && cmdline) {
9059                                 minusc = p;     /* command is after shell args */
9060                         } else if (c == 'o') {
9061                                 minus_o(*argptr, val);
9062                                 if (*argptr)
9063                                         argptr++;
9064                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9065                                 isloginsh = 1;
9066                         /* bash does not accept +-login, we also won't */
9067                         } else if (cmdline && val && (c == '-')) { /* long options */
9068                                 if (strcmp(p, "login") == 0)
9069                                         isloginsh = 1;
9070                                 break;
9071                         } else {
9072                                 setoption(c, val);
9073                         }
9074                 }
9075         }
9076 }
9077
9078 /*
9079  * The shift builtin command.
9080  */
9081 static int
9082 shiftcmd(int argc, char **argv)
9083 {
9084         int n;
9085         char **ap1, **ap2;
9086
9087         n = 1;
9088         if (argc > 1)
9089                 n = number(argv[1]);
9090         if (n > shellparam.nparam)
9091                 ash_msg_and_raise_error("can't shift that many");
9092         INT_OFF;
9093         shellparam.nparam -= n;
9094         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9095                 if (shellparam.malloc)
9096                         free(*ap1);
9097         }
9098         ap2 = shellparam.p;
9099         while ((*ap2++ = *ap1++) != NULL);
9100 #if ENABLE_ASH_GETOPTS
9101         shellparam.optind = 1;
9102         shellparam.optoff = -1;
9103 #endif
9104         INT_ON;
9105         return 0;
9106 }
9107
9108 /*
9109  * POSIX requires that 'set' (but not export or readonly) output the
9110  * variables in lexicographic order - by the locale's collating order (sigh).
9111  * Maybe we could keep them in an ordered balanced binary tree
9112  * instead of hashed lists.
9113  * For now just roll 'em through qsort for printing...
9114  */
9115 static int
9116 showvars(const char *sep_prefix, int on, int off)
9117 {
9118         const char *sep;
9119         char **ep, **epend;
9120
9121         ep = listvars(on, off, &epend);
9122         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9123
9124         sep = *sep_prefix ? " " : sep_prefix;
9125
9126         for (; ep < epend; ep++) {
9127                 const char *p;
9128                 const char *q;
9129
9130                 p = strchrnul(*ep, '=');
9131                 q = nullstr;
9132                 if (*p)
9133                         q = single_quote(++p);
9134                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9135         }
9136         return 0;
9137 }
9138
9139 /*
9140  * The set command builtin.
9141  */
9142 static int
9143 setcmd(int argc, char **argv)
9144 {
9145         if (argc == 1)
9146                 return showvars(nullstr, 0, VUNSET);
9147         INT_OFF;
9148         options(0);
9149         optschanged();
9150         if (*argptr != NULL) {
9151                 setparam(argptr);
9152         }
9153         INT_ON;
9154         return 0;
9155 }
9156
9157 #if ENABLE_ASH_RANDOM_SUPPORT
9158 /* Roughly copied from bash.. */
9159 static void
9160 change_random(const char *value)
9161 {
9162         if (value == NULL) {
9163                 /* "get", generate */
9164                 char buf[16];
9165
9166                 rseed = rseed * 1103515245 + 12345;
9167                 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9168                 /* set without recursion */
9169                 setvar(vrandom.text, buf, VNOFUNC);
9170                 vrandom.flags &= ~VNOFUNC;
9171         } else {
9172                 /* set/reset */
9173                 rseed = strtoul(value, (char **)NULL, 10);
9174         }
9175 }
9176 #endif
9177
9178 #if ENABLE_ASH_GETOPTS
9179 static int
9180 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9181 {
9182         char *p, *q;
9183         char c = '?';
9184         int done = 0;
9185         int err = 0;
9186         char s[12];
9187         char **optnext;
9188
9189         if (*param_optind < 1)
9190                 return 1;
9191         optnext = optfirst + *param_optind - 1;
9192
9193         if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9194                 p = NULL;
9195         else
9196                 p = optnext[-1] + *optoff;
9197         if (p == NULL || *p == '\0') {
9198                 /* Current word is done, advance */
9199                 p = *optnext;
9200                 if (p == NULL || *p != '-' || *++p == '\0') {
9201  atend:
9202                         p = NULL;
9203                         done = 1;
9204                         goto out;
9205                 }
9206                 optnext++;
9207                 if (LONE_DASH(p))        /* check for "--" */
9208                         goto atend;
9209         }
9210
9211         c = *p++;
9212         for (q = optstr; *q != c; ) {
9213                 if (*q == '\0') {
9214                         if (optstr[0] == ':') {
9215                                 s[0] = c;
9216                                 s[1] = '\0';
9217                                 err |= setvarsafe("OPTARG", s, 0);
9218                         } else {
9219                                 fprintf(stderr, "Illegal option -%c\n", c);
9220                                 unsetvar("OPTARG");
9221                         }
9222                         c = '?';
9223                         goto out;
9224                 }
9225                 if (*++q == ':')
9226                         q++;
9227         }
9228
9229         if (*++q == ':') {
9230                 if (*p == '\0' && (p = *optnext) == NULL) {
9231                         if (optstr[0] == ':') {
9232                                 s[0] = c;
9233                                 s[1] = '\0';
9234                                 err |= setvarsafe("OPTARG", s, 0);
9235                                 c = ':';
9236                         } else {
9237                                 fprintf(stderr, "No arg for -%c option\n", c);
9238                                 unsetvar("OPTARG");
9239                                 c = '?';
9240                         }
9241                         goto out;
9242                 }
9243
9244                 if (p == *optnext)
9245                         optnext++;
9246                 err |= setvarsafe("OPTARG", p, 0);
9247                 p = NULL;
9248         } else
9249                 err |= setvarsafe("OPTARG", nullstr, 0);
9250  out:
9251         *optoff = p ? p - *(optnext - 1) : -1;
9252         *param_optind = optnext - optfirst + 1;
9253         fmtstr(s, sizeof(s), "%d", *param_optind);
9254         err |= setvarsafe("OPTIND", s, VNOFUNC);
9255         s[0] = c;
9256         s[1] = '\0';
9257         err |= setvarsafe(optvar, s, 0);
9258         if (err) {
9259                 *param_optind = 1;
9260                 *optoff = -1;
9261                 flush_stdout_stderr();
9262                 raise_exception(EXERROR);
9263         }
9264         return done;
9265 }
9266
9267 /*
9268  * The getopts builtin.  Shellparam.optnext points to the next argument
9269  * to be processed.  Shellparam.optptr points to the next character to
9270  * be processed in the current argument.  If shellparam.optnext is NULL,
9271  * then it's the first time getopts has been called.
9272  */
9273 static int
9274 getoptscmd(int argc, char **argv)
9275 {
9276         char **optbase;
9277
9278         if (argc < 3)
9279                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9280         if (argc == 3) {
9281                 optbase = shellparam.p;
9282                 if (shellparam.optind > shellparam.nparam + 1) {
9283                         shellparam.optind = 1;
9284                         shellparam.optoff = -1;
9285                 }
9286         } else {
9287                 optbase = &argv[3];
9288                 if (shellparam.optind > argc - 2) {
9289                         shellparam.optind = 1;
9290                         shellparam.optoff = -1;
9291                 }
9292         }
9293
9294         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9295                         &shellparam.optoff);
9296 }
9297 #endif /* ASH_GETOPTS */
9298
9299
9300 /* ============ Shell parser */
9301
9302 /*
9303  * NEOF is returned by parsecmd when it encounters an end of file.  It
9304  * must be distinct from NULL, so we use the address of a variable that
9305  * happens to be handy.
9306  */
9307 static smallint tokpushback;           /* last token pushed back */
9308 #define NEOF ((union node *)&tokpushback)
9309 static smallint parsebackquote;        /* nonzero if we are inside backquotes */
9310 static int lasttoken;                  /* last token read */
9311 static char *wordtext;                 /* text of last word returned by readtoken */
9312 static struct nodelist *backquotelist;
9313 static union node *redirnode;
9314 static struct heredoc *heredoc;
9315 static smallint quoteflag;             /* set if (part of) last token was quoted */
9316
9317 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9318 static void
9319 raise_error_syntax(const char *msg)
9320 {
9321         ash_msg_and_raise_error("syntax error: %s", msg);
9322         /* NOTREACHED */
9323 }
9324
9325 /*
9326  * Called when an unexpected token is read during the parse.  The argument
9327  * is the token that is expected, or -1 if more than one type of token can
9328  * occur at this point.
9329  */
9330 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9331 static void
9332 raise_error_unexpected_syntax(int token)
9333 {
9334         char msg[64];
9335         int l;
9336
9337         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9338         if (token >= 0)
9339                 sprintf(msg + l, " (expecting %s)", tokname(token));
9340         raise_error_syntax(msg);
9341         /* NOTREACHED */
9342 }
9343
9344 #define EOFMARKLEN 79
9345
9346 struct heredoc {
9347         struct heredoc *next;   /* next here document in list */
9348         union node *here;               /* redirection node */
9349         char *eofmark;          /* string indicating end of input */
9350         int striptabs;          /* if set, strip leading tabs */
9351 };
9352
9353 static struct heredoc *heredoclist;    /* list of here documents to read */
9354
9355 /* parsing is heavily cross-recursive, need these forward decls */
9356 static union node *andor(void);
9357 static union node *pipeline(void);
9358 static union node *parse_command(void);
9359 static void parseheredoc(void);
9360 static char peektoken(void);
9361 static int readtoken(void);
9362
9363 static union node *
9364 list(int nlflag)
9365 {
9366         union node *n1, *n2, *n3;
9367         int tok;
9368
9369         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9370         if (nlflag == 2 && peektoken())
9371                 return NULL;
9372         n1 = NULL;
9373         for (;;) {
9374                 n2 = andor();
9375                 tok = readtoken();
9376                 if (tok == TBACKGND) {
9377                         if (n2->type == NPIPE) {
9378                                 n2->npipe.backgnd = 1;
9379                         } else {
9380                                 if (n2->type != NREDIR) {
9381                                         n3 = stalloc(sizeof(struct nredir));
9382                                         n3->nredir.n = n2;
9383                                         n3->nredir.redirect = NULL;
9384                                         n2 = n3;
9385                                 }
9386                                 n2->type = NBACKGND;
9387                         }
9388                 }
9389                 if (n1 == NULL) {
9390                         n1 = n2;
9391                 } else {
9392                         n3 = stalloc(sizeof(struct nbinary));
9393                         n3->type = NSEMI;
9394                         n3->nbinary.ch1 = n1;
9395                         n3->nbinary.ch2 = n2;
9396                         n1 = n3;
9397                 }
9398                 switch (tok) {
9399                 case TBACKGND:
9400                 case TSEMI:
9401                         tok = readtoken();
9402                         /* fall through */
9403                 case TNL:
9404                         if (tok == TNL) {
9405                                 parseheredoc();
9406                                 if (nlflag == 1)
9407                                         return n1;
9408                         } else {
9409                                 tokpushback = 1;
9410                         }
9411                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9412                         if (peektoken())
9413                                 return n1;
9414                         break;
9415                 case TEOF:
9416                         if (heredoclist)
9417                                 parseheredoc();
9418                         else
9419                                 pungetc();              /* push back EOF on input */
9420                         return n1;
9421                 default:
9422                         if (nlflag == 1)
9423                                 raise_error_unexpected_syntax(-1);
9424                         tokpushback = 1;
9425                         return n1;
9426                 }
9427         }
9428 }
9429
9430 static union node *
9431 andor(void)
9432 {
9433         union node *n1, *n2, *n3;
9434         int t;
9435
9436         n1 = pipeline();
9437         for (;;) {
9438                 t = readtoken();
9439                 if (t == TAND) {
9440                         t = NAND;
9441                 } else if (t == TOR) {
9442                         t = NOR;
9443                 } else {
9444                         tokpushback = 1;
9445                         return n1;
9446                 }
9447                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9448                 n2 = pipeline();
9449                 n3 = stalloc(sizeof(struct nbinary));
9450                 n3->type = t;
9451                 n3->nbinary.ch1 = n1;
9452                 n3->nbinary.ch2 = n2;
9453                 n1 = n3;
9454         }
9455 }
9456
9457 static union node *
9458 pipeline(void)
9459 {
9460         union node *n1, *n2, *pipenode;
9461         struct nodelist *lp, *prev;
9462         int negate;
9463
9464         negate = 0;
9465         TRACE(("pipeline: entered\n"));
9466         if (readtoken() == TNOT) {
9467                 negate = !negate;
9468                 checkkwd = CHKKWD | CHKALIAS;
9469         } else
9470                 tokpushback = 1;
9471         n1 = parse_command();
9472         if (readtoken() == TPIPE) {
9473                 pipenode = stalloc(sizeof(struct npipe));
9474                 pipenode->type = NPIPE;
9475                 pipenode->npipe.backgnd = 0;
9476                 lp = stalloc(sizeof(struct nodelist));
9477                 pipenode->npipe.cmdlist = lp;
9478                 lp->n = n1;
9479                 do {
9480                         prev = lp;
9481                         lp = stalloc(sizeof(struct nodelist));
9482                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9483                         lp->n = parse_command();
9484                         prev->next = lp;
9485                 } while (readtoken() == TPIPE);
9486                 lp->next = NULL;
9487                 n1 = pipenode;
9488         }
9489         tokpushback = 1;
9490         if (negate) {
9491                 n2 = stalloc(sizeof(struct nnot));
9492                 n2->type = NNOT;
9493                 n2->nnot.com = n1;
9494                 return n2;
9495         }
9496         return n1;
9497 }
9498
9499 static union node *
9500 makename(void)
9501 {
9502         union node *n;
9503
9504         n = stalloc(sizeof(struct narg));
9505         n->type = NARG;
9506         n->narg.next = NULL;
9507         n->narg.text = wordtext;
9508         n->narg.backquote = backquotelist;
9509         return n;
9510 }
9511
9512 static void
9513 fixredir(union node *n, const char *text, int err)
9514 {
9515         TRACE(("Fix redir %s %d\n", text, err));
9516         if (!err)
9517                 n->ndup.vname = NULL;
9518
9519         if (isdigit(text[0]) && text[1] == '\0')
9520                 n->ndup.dupfd = text[0] - '0';
9521         else if (LONE_DASH(text))
9522                 n->ndup.dupfd = -1;
9523         else {
9524                 if (err)
9525                         raise_error_syntax("Bad fd number");
9526                 n->ndup.vname = makename();
9527         }
9528 }
9529
9530 /*
9531  * Returns true if the text contains nothing to expand (no dollar signs
9532  * or backquotes).
9533  */
9534 static int
9535 noexpand(char *text)
9536 {
9537         char *p;
9538         char c;
9539
9540         p = text;
9541         while ((c = *p++) != '\0') {
9542                 if (c == CTLQUOTEMARK)
9543                         continue;
9544                 if (c == CTLESC)
9545                         p++;
9546                 else if (SIT(c, BASESYNTAX) == CCTL)
9547                         return 0;
9548         }
9549         return 1;
9550 }
9551
9552 static void
9553 parsefname(void)
9554 {
9555         union node *n = redirnode;
9556
9557         if (readtoken() != TWORD)
9558                 raise_error_unexpected_syntax(-1);
9559         if (n->type == NHERE) {
9560                 struct heredoc *here = heredoc;
9561                 struct heredoc *p;
9562                 int i;
9563
9564                 if (quoteflag == 0)
9565                         n->type = NXHERE;
9566                 TRACE(("Here document %d\n", n->type));
9567                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9568                         raise_error_syntax("Illegal eof marker for << redirection");
9569                 rmescapes(wordtext);
9570                 here->eofmark = wordtext;
9571                 here->next = NULL;
9572                 if (heredoclist == NULL)
9573                         heredoclist = here;
9574                 else {
9575                         for (p = heredoclist; p->next; p = p->next);
9576                         p->next = here;
9577                 }
9578         } else if (n->type == NTOFD || n->type == NFROMFD) {
9579                 fixredir(n, wordtext, 0);
9580         } else {
9581                 n->nfile.fname = makename();
9582         }
9583 }
9584
9585 static union node *
9586 simplecmd(void)
9587 {
9588         union node *args, **app;
9589         union node *n = NULL;
9590         union node *vars, **vpp;
9591         union node **rpp, *redir;
9592         int savecheckkwd;
9593
9594         args = NULL;
9595         app = &args;
9596         vars = NULL;
9597         vpp = &vars;
9598         redir = NULL;
9599         rpp = &redir;
9600
9601         savecheckkwd = CHKALIAS;
9602         for (;;) {
9603                 checkkwd = savecheckkwd;
9604                 switch (readtoken()) {
9605                 case TWORD:
9606                         n = stalloc(sizeof(struct narg));
9607                         n->type = NARG;
9608                         n->narg.text = wordtext;
9609                         n->narg.backquote = backquotelist;
9610                         if (savecheckkwd && isassignment(wordtext)) {
9611                                 *vpp = n;
9612                                 vpp = &n->narg.next;
9613                         } else {
9614                                 *app = n;
9615                                 app = &n->narg.next;
9616                                 savecheckkwd = 0;
9617                         }
9618                         break;
9619                 case TREDIR:
9620                         *rpp = n = redirnode;
9621                         rpp = &n->nfile.next;
9622                         parsefname();   /* read name of redirection file */
9623                         break;
9624                 case TLP:
9625                         if (args && app == &args->narg.next
9626                          && !vars && !redir
9627                         ) {
9628                                 struct builtincmd *bcmd;
9629                                 const char *name;
9630
9631                                 /* We have a function */
9632                                 if (readtoken() != TRP)
9633                                         raise_error_unexpected_syntax(TRP);
9634                                 name = n->narg.text;
9635                                 if (!goodname(name)
9636                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9637                                 ) {
9638                                         raise_error_syntax("Bad function name");
9639                                 }
9640                                 n->type = NDEFUN;
9641                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9642                                 n->narg.next = parse_command();
9643                                 return n;
9644                         }
9645                         /* fall through */
9646                 default:
9647                         tokpushback = 1;
9648                         goto out;
9649                 }
9650         }
9651  out:
9652         *app = NULL;
9653         *vpp = NULL;
9654         *rpp = NULL;
9655         n = stalloc(sizeof(struct ncmd));
9656         n->type = NCMD;
9657         n->ncmd.args = args;
9658         n->ncmd.assign = vars;
9659         n->ncmd.redirect = redir;
9660         return n;
9661 }
9662
9663 static union node *
9664 parse_command(void)
9665 {
9666         union node *n1, *n2;
9667         union node *ap, **app;
9668         union node *cp, **cpp;
9669         union node *redir, **rpp;
9670         union node **rpp2;
9671         int t;
9672
9673         redir = NULL;
9674         rpp2 = &redir;
9675
9676         switch (readtoken()) {
9677         default:
9678                 raise_error_unexpected_syntax(-1);
9679                 /* NOTREACHED */
9680         case TIF:
9681                 n1 = stalloc(sizeof(struct nif));
9682                 n1->type = NIF;
9683                 n1->nif.test = list(0);
9684                 if (readtoken() != TTHEN)
9685                         raise_error_unexpected_syntax(TTHEN);
9686                 n1->nif.ifpart = list(0);
9687                 n2 = n1;
9688                 while (readtoken() == TELIF) {
9689                         n2->nif.elsepart = stalloc(sizeof(struct nif));
9690                         n2 = n2->nif.elsepart;
9691                         n2->type = NIF;
9692                         n2->nif.test = list(0);
9693                         if (readtoken() != TTHEN)
9694                                 raise_error_unexpected_syntax(TTHEN);
9695                         n2->nif.ifpart = list(0);
9696                 }
9697                 if (lasttoken == TELSE)
9698                         n2->nif.elsepart = list(0);
9699                 else {
9700                         n2->nif.elsepart = NULL;
9701                         tokpushback = 1;
9702                 }
9703                 t = TFI;
9704                 break;
9705         case TWHILE:
9706         case TUNTIL: {
9707                 int got;
9708                 n1 = stalloc(sizeof(struct nbinary));
9709                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9710                 n1->nbinary.ch1 = list(0);
9711                 got = readtoken();
9712                 if (got != TDO) {
9713                         TRACE(("expecting DO got %s %s\n", tokname(got),
9714                                         got == TWORD ? wordtext : ""));
9715                         raise_error_unexpected_syntax(TDO);
9716                 }
9717                 n1->nbinary.ch2 = list(0);
9718                 t = TDONE;
9719                 break;
9720         }
9721         case TFOR:
9722                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9723                         raise_error_syntax("Bad for loop variable");
9724                 n1 = stalloc(sizeof(struct nfor));
9725                 n1->type = NFOR;
9726                 n1->nfor.var = wordtext;
9727                 checkkwd = CHKKWD | CHKALIAS;
9728                 if (readtoken() == TIN) {
9729                         app = &ap;
9730                         while (readtoken() == TWORD) {
9731                                 n2 = stalloc(sizeof(struct narg));
9732                                 n2->type = NARG;
9733                                 n2->narg.text = wordtext;
9734                                 n2->narg.backquote = backquotelist;
9735                                 *app = n2;
9736                                 app = &n2->narg.next;
9737                         }
9738                         *app = NULL;
9739                         n1->nfor.args = ap;
9740                         if (lasttoken != TNL && lasttoken != TSEMI)
9741                                 raise_error_unexpected_syntax(-1);
9742                 } else {
9743                         n2 = stalloc(sizeof(struct narg));
9744                         n2->type = NARG;
9745                         n2->narg.text = (char *)dolatstr;
9746                         n2->narg.backquote = NULL;
9747                         n2->narg.next = NULL;
9748                         n1->nfor.args = n2;
9749                         /*
9750                          * Newline or semicolon here is optional (but note
9751                          * that the original Bourne shell only allowed NL).
9752                          */
9753                         if (lasttoken != TNL && lasttoken != TSEMI)
9754                                 tokpushback = 1;
9755                 }
9756                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9757                 if (readtoken() != TDO)
9758                         raise_error_unexpected_syntax(TDO);
9759                 n1->nfor.body = list(0);
9760                 t = TDONE;
9761                 break;
9762         case TCASE:
9763                 n1 = stalloc(sizeof(struct ncase));
9764                 n1->type = NCASE;
9765                 if (readtoken() != TWORD)
9766                         raise_error_unexpected_syntax(TWORD);
9767                 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9768                 n2->type = NARG;
9769                 n2->narg.text = wordtext;
9770                 n2->narg.backquote = backquotelist;
9771                 n2->narg.next = NULL;
9772                 do {
9773                         checkkwd = CHKKWD | CHKALIAS;
9774                 } while (readtoken() == TNL);
9775                 if (lasttoken != TIN)
9776                         raise_error_unexpected_syntax(TIN);
9777                 cpp = &n1->ncase.cases;
9778  next_case:
9779                 checkkwd = CHKNL | CHKKWD;
9780                 t = readtoken();
9781                 while (t != TESAC) {
9782                         if (lasttoken == TLP)
9783                                 readtoken();
9784                         *cpp = cp = stalloc(sizeof(struct nclist));
9785                         cp->type = NCLIST;
9786                         app = &cp->nclist.pattern;
9787                         for (;;) {
9788                                 *app = ap = stalloc(sizeof(struct narg));
9789                                 ap->type = NARG;
9790                                 ap->narg.text = wordtext;
9791                                 ap->narg.backquote = backquotelist;
9792                                 if (readtoken() != TPIPE)
9793                                         break;
9794                                 app = &ap->narg.next;
9795                                 readtoken();
9796                         }
9797                         ap->narg.next = NULL;
9798                         if (lasttoken != TRP)
9799                                 raise_error_unexpected_syntax(TRP);
9800                         cp->nclist.body = list(2);
9801
9802                         cpp = &cp->nclist.next;
9803
9804                         checkkwd = CHKNL | CHKKWD;
9805                         t = readtoken();
9806                         if (t != TESAC) {
9807                                 if (t != TENDCASE)
9808                                         raise_error_unexpected_syntax(TENDCASE);
9809                                 goto next_case;
9810                         }
9811                 }
9812                 *cpp = NULL;
9813                 goto redir;
9814         case TLP:
9815                 n1 = stalloc(sizeof(struct nredir));
9816                 n1->type = NSUBSHELL;
9817                 n1->nredir.n = list(0);
9818                 n1->nredir.redirect = NULL;
9819                 t = TRP;
9820                 break;
9821         case TBEGIN:
9822                 n1 = list(0);
9823                 t = TEND;
9824                 break;
9825         case TWORD:
9826         case TREDIR:
9827                 tokpushback = 1;
9828                 return simplecmd();
9829         }
9830
9831         if (readtoken() != t)
9832                 raise_error_unexpected_syntax(t);
9833
9834  redir:
9835         /* Now check for redirection which may follow command */
9836         checkkwd = CHKKWD | CHKALIAS;
9837         rpp = rpp2;
9838         while (readtoken() == TREDIR) {
9839                 *rpp = n2 = redirnode;
9840                 rpp = &n2->nfile.next;
9841                 parsefname();
9842         }
9843         tokpushback = 1;
9844         *rpp = NULL;
9845         if (redir) {
9846                 if (n1->type != NSUBSHELL) {
9847                         n2 = stalloc(sizeof(struct nredir));
9848                         n2->type = NREDIR;
9849                         n2->nredir.n = n1;
9850                         n1 = n2;
9851                 }
9852                 n1->nredir.redirect = redir;
9853         }
9854         return n1;
9855 }
9856
9857 /*
9858  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
9859  * is not NULL, read a here document.  In the latter case, eofmark is the
9860  * word which marks the end of the document and striptabs is true if
9861  * leading tabs should be stripped from the document.  The argument firstc
9862  * is the first character of the input token or document.
9863  *
9864  * Because C does not have internal subroutines, I have simulated them
9865  * using goto's to implement the subroutine linkage.  The following macros
9866  * will run code that appears at the end of readtoken1.
9867  */
9868
9869 #define CHECKEND()      {goto checkend; checkend_return:;}
9870 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
9871 #define PARSESUB()      {goto parsesub; parsesub_return:;}
9872 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9873 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9874 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
9875
9876 static int
9877 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9878 {
9879         /* NB: syntax parameter fits into smallint */
9880         int c = firstc;
9881         char *out;
9882         int len;
9883         char line[EOFMARKLEN + 1];
9884         struct nodelist *bqlist;
9885         smallint quotef;
9886         smallint dblquote;
9887         smallint oldstyle;
9888         smallint prevsyntax; /* syntax before arithmetic */
9889 #if ENABLE_ASH_EXPAND_PRMT
9890         smallint pssyntax;   /* we are expanding a prompt string */
9891 #endif
9892         int varnest;         /* levels of variables expansion */
9893         int arinest;         /* levels of arithmetic expansion */
9894         int parenlevel;      /* levels of parens in arithmetic */
9895         int dqvarnest;       /* levels of variables expansion within double quotes */
9896
9897 #if __GNUC__
9898         /* Avoid longjmp clobbering */
9899         (void) &out;
9900         (void) &quotef;
9901         (void) &dblquote;
9902         (void) &varnest;
9903         (void) &arinest;
9904         (void) &parenlevel;
9905         (void) &dqvarnest;
9906         (void) &oldstyle;
9907         (void) &prevsyntax;
9908         (void) &syntax;
9909 #endif
9910         startlinno = plinno;
9911         bqlist = NULL;
9912         quotef = 0;
9913         oldstyle = 0;
9914         prevsyntax = 0;
9915 #if ENABLE_ASH_EXPAND_PRMT
9916         pssyntax = (syntax == PSSYNTAX);
9917         if (pssyntax)
9918                 syntax = DQSYNTAX;
9919 #endif
9920         dblquote = (syntax == DQSYNTAX);
9921         varnest = 0;
9922         arinest = 0;
9923         parenlevel = 0;
9924         dqvarnest = 0;
9925
9926         STARTSTACKSTR(out);
9927         loop: { /* for each line, until end of word */
9928                 CHECKEND();     /* set c to PEOF if at end of here document */
9929                 for (;;) {      /* until end of line or end of word */
9930                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
9931                         switch (SIT(c, syntax)) {
9932                         case CNL:       /* '\n' */
9933                                 if (syntax == BASESYNTAX)
9934                                         goto endword;   /* exit outer loop */
9935                                 USTPUTC(c, out);
9936                                 plinno++;
9937                                 if (doprompt)
9938                                         setprompt(2);
9939                                 c = pgetc();
9940                                 goto loop;              /* continue outer loop */
9941                         case CWORD:
9942                                 USTPUTC(c, out);
9943                                 break;
9944                         case CCTL:
9945                                 if (eofmark == NULL || dblquote)
9946                                         USTPUTC(CTLESC, out);
9947                                 USTPUTC(c, out);
9948                                 break;
9949                         case CBACK:     /* backslash */
9950                                 c = pgetc2();
9951                                 if (c == PEOF) {
9952                                         USTPUTC(CTLESC, out);
9953                                         USTPUTC('\\', out);
9954                                         pungetc();
9955                                 } else if (c == '\n') {
9956                                         if (doprompt)
9957                                                 setprompt(2);
9958                                 } else {
9959 #if ENABLE_ASH_EXPAND_PRMT
9960                                         if (c == '$' && pssyntax) {
9961                                                 USTPUTC(CTLESC, out);
9962                                                 USTPUTC('\\', out);
9963                                         }
9964 #endif
9965                                         if (dblquote &&
9966                                                 c != '\\' && c != '`' &&
9967                                                 c != '$' && (
9968                                                         c != '"' ||
9969                                                         eofmark != NULL)
9970                                         ) {
9971                                                 USTPUTC(CTLESC, out);
9972                                                 USTPUTC('\\', out);
9973                                         }
9974                                         if (SIT(c, SQSYNTAX) == CCTL)
9975                                                 USTPUTC(CTLESC, out);
9976                                         USTPUTC(c, out);
9977                                         quotef = 1;
9978                                 }
9979                                 break;
9980                         case CSQUOTE:
9981                                 syntax = SQSYNTAX;
9982  quotemark:
9983                                 if (eofmark == NULL) {
9984                                         USTPUTC(CTLQUOTEMARK, out);
9985                                 }
9986                                 break;
9987                         case CDQUOTE:
9988                                 syntax = DQSYNTAX;
9989                                 dblquote = 1;
9990                                 goto quotemark;
9991                         case CENDQUOTE:
9992                                 if (eofmark != NULL && arinest == 0
9993                                  && varnest == 0
9994                                 ) {
9995                                         USTPUTC(c, out);
9996                                 } else {
9997                                         if (dqvarnest == 0) {
9998                                                 syntax = BASESYNTAX;
9999                                                 dblquote = 0;
10000                                         }
10001                                         quotef = 1;
10002                                         goto quotemark;
10003                                 }
10004                                 break;
10005                         case CVAR:      /* '$' */
10006                                 PARSESUB();             /* parse substitution */
10007                                 break;
10008                         case CENDVAR:   /* '}' */
10009                                 if (varnest > 0) {
10010                                         varnest--;
10011                                         if (dqvarnest > 0) {
10012                                                 dqvarnest--;
10013                                         }
10014                                         USTPUTC(CTLENDVAR, out);
10015                                 } else {
10016                                         USTPUTC(c, out);
10017                                 }
10018                                 break;
10019 #if ENABLE_ASH_MATH_SUPPORT
10020                         case CLP:       /* '(' in arithmetic */
10021                                 parenlevel++;
10022                                 USTPUTC(c, out);
10023                                 break;
10024                         case CRP:       /* ')' in arithmetic */
10025                                 if (parenlevel > 0) {
10026                                         USTPUTC(c, out);
10027                                         --parenlevel;
10028                                 } else {
10029                                         if (pgetc() == ')') {
10030                                                 if (--arinest == 0) {
10031                                                         USTPUTC(CTLENDARI, out);
10032                                                         syntax = prevsyntax;
10033                                                         dblquote = (syntax == DQSYNTAX);
10034                                                 } else
10035                                                         USTPUTC(')', out);
10036                                         } else {
10037                                                 /*
10038                                                  * unbalanced parens
10039                                                  *  (don't 2nd guess - no error)
10040                                                  */
10041                                                 pungetc();
10042                                                 USTPUTC(')', out);
10043                                         }
10044                                 }
10045                                 break;
10046 #endif
10047                         case CBQUOTE:   /* '`' */
10048                                 PARSEBACKQOLD();
10049                                 break;
10050                         case CENDFILE:
10051                                 goto endword;           /* exit outer loop */
10052                         case CIGN:
10053                                 break;
10054                         default:
10055                                 if (varnest == 0)
10056                                         goto endword;   /* exit outer loop */
10057 #if ENABLE_ASH_ALIAS
10058                                 if (c != PEOA)
10059 #endif
10060                                         USTPUTC(c, out);
10061
10062                         }
10063                         c = pgetc_macro();
10064                 }
10065         }
10066  endword:
10067 #if ENABLE_ASH_MATH_SUPPORT
10068         if (syntax == ARISYNTAX)
10069                 raise_error_syntax("Missing '))'");
10070 #endif
10071         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10072                 raise_error_syntax("Unterminated quoted string");
10073         if (varnest != 0) {
10074                 startlinno = plinno;
10075                 /* { */
10076                 raise_error_syntax("Missing '}'");
10077         }
10078         USTPUTC('\0', out);
10079         len = out - (char *)stackblock();
10080         out = stackblock();
10081         if (eofmark == NULL) {
10082                 if ((c == '>' || c == '<')
10083                  && quotef == 0
10084                  && len <= 2
10085                  && (*out == '\0' || isdigit(*out))) {
10086                         PARSEREDIR();
10087                         return lasttoken = TREDIR;
10088                 } else {
10089                         pungetc();
10090                 }
10091         }
10092         quoteflag = quotef;
10093         backquotelist = bqlist;
10094         grabstackblock(len);
10095         wordtext = out;
10096         lasttoken = TWORD;
10097         return lasttoken;
10098 /* end of readtoken routine */
10099
10100 /*
10101  * Check to see whether we are at the end of the here document.  When this
10102  * is called, c is set to the first character of the next input line.  If
10103  * we are at the end of the here document, this routine sets the c to PEOF.
10104  */
10105 checkend: {
10106         if (eofmark) {
10107 #if ENABLE_ASH_ALIAS
10108                 if (c == PEOA) {
10109                         c = pgetc2();
10110                 }
10111 #endif
10112                 if (striptabs) {
10113                         while (c == '\t') {
10114                                 c = pgetc2();
10115                         }
10116                 }
10117                 if (c == *eofmark) {
10118                         if (pfgets(line, sizeof(line)) != NULL) {
10119                                 char *p, *q;
10120
10121                                 p = line;
10122                                 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10123                                 if (*p == '\n' && *q == '\0') {
10124                                         c = PEOF;
10125                                         plinno++;
10126                                         needprompt = doprompt;
10127                                 } else {
10128                                         pushstring(line, NULL);
10129                                 }
10130                         }
10131                 }
10132         }
10133         goto checkend_return;
10134 }
10135
10136 /*
10137  * Parse a redirection operator.  The variable "out" points to a string
10138  * specifying the fd to be redirected.  The variable "c" contains the
10139  * first character of the redirection operator.
10140  */
10141 parseredir: {
10142         char fd = *out;
10143         union node *np;
10144
10145         np = stalloc(sizeof(struct nfile));
10146         if (c == '>') {
10147                 np->nfile.fd = 1;
10148                 c = pgetc();
10149                 if (c == '>')
10150                         np->type = NAPPEND;
10151                 else if (c == '|')
10152                         np->type = NCLOBBER;
10153                 else if (c == '&')
10154                         np->type = NTOFD;
10155                 else {
10156                         np->type = NTO;
10157                         pungetc();
10158                 }
10159         } else {        /* c == '<' */
10160                 np->nfile.fd = 0;
10161                 c = pgetc();
10162                 switch (c) {
10163                 case '<':
10164                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10165                                 np = stalloc(sizeof(struct nhere));
10166                                 np->nfile.fd = 0;
10167                         }
10168                         np->type = NHERE;
10169                         heredoc = stalloc(sizeof(struct heredoc));
10170                         heredoc->here = np;
10171                         c = pgetc();
10172                         if (c == '-') {
10173                                 heredoc->striptabs = 1;
10174                         } else {
10175                                 heredoc->striptabs = 0;
10176                                 pungetc();
10177                         }
10178                         break;
10179
10180                 case '&':
10181                         np->type = NFROMFD;
10182                         break;
10183
10184                 case '>':
10185                         np->type = NFROMTO;
10186                         break;
10187
10188                 default:
10189                         np->type = NFROM;
10190                         pungetc();
10191                         break;
10192                 }
10193         }
10194         if (fd != '\0')
10195                 np->nfile.fd = fd - '0';
10196         redirnode = np;
10197         goto parseredir_return;
10198 }
10199
10200 /*
10201  * Parse a substitution.  At this point, we have read the dollar sign
10202  * and nothing else.
10203  */
10204
10205 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10206  * (assuming ascii char codes, as the original implementation did) */
10207 #define is_special(c) \
10208         ((((unsigned int)c) - 33 < 32) \
10209                         && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10210 parsesub: {
10211         int subtype;
10212         int typeloc;
10213         int flags;
10214         char *p;
10215         static const char types[] ALIGN1 = "}-+?=";
10216
10217         c = pgetc();
10218         if (
10219                 c <= PEOA_OR_PEOF  ||
10220                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10221         ) {
10222                 USTPUTC('$', out);
10223                 pungetc();
10224         } else if (c == '(') {  /* $(command) or $((arith)) */
10225                 if (pgetc() == '(') {
10226 #if ENABLE_ASH_MATH_SUPPORT
10227                         PARSEARITH();
10228 #else
10229                         raise_error_syntax("We unsupport $((arith))");
10230 #endif
10231                 } else {
10232                         pungetc();
10233                         PARSEBACKQNEW();
10234                 }
10235         } else {
10236                 USTPUTC(CTLVAR, out);
10237                 typeloc = out - (char *)stackblock();
10238                 USTPUTC(VSNORMAL, out);
10239                 subtype = VSNORMAL;
10240                 if (c == '{') {
10241                         c = pgetc();
10242                         if (c == '#') {
10243                                 c = pgetc();
10244                                 if (c == '}')
10245                                         c = '#';
10246                                 else
10247                                         subtype = VSLENGTH;
10248                         } else
10249                                 subtype = 0;
10250                 }
10251                 if (c > PEOA_OR_PEOF && is_name(c)) {
10252                         do {
10253                                 STPUTC(c, out);
10254                                 c = pgetc();
10255                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10256                 } else if (isdigit(c)) {
10257                         do {
10258                                 STPUTC(c, out);
10259                                 c = pgetc();
10260                         } while (isdigit(c));
10261                 } else if (is_special(c)) {
10262                         USTPUTC(c, out);
10263                         c = pgetc();
10264                 } else
10265  badsub:                raise_error_syntax("Bad substitution");
10266
10267                 STPUTC('=', out);
10268                 flags = 0;
10269                 if (subtype == 0) {
10270                         switch (c) {
10271                         case ':':
10272                                 flags = VSNUL;
10273                                 c = pgetc();
10274                                 /*FALLTHROUGH*/
10275                         default:
10276                                 p = strchr(types, c);
10277                                 if (p == NULL)
10278                                         goto badsub;
10279                                 subtype = p - types + VSNORMAL;
10280                                 break;
10281                         case '%':
10282                         case '#':
10283                                 {
10284                                         int cc = c;
10285                                         subtype = c == '#' ? VSTRIMLEFT :
10286                                                              VSTRIMRIGHT;
10287                                         c = pgetc();
10288                                         if (c == cc)
10289                                                 subtype++;
10290                                         else
10291                                                 pungetc();
10292                                         break;
10293                                 }
10294                         }
10295                 } else {
10296                         pungetc();
10297                 }
10298                 if (dblquote || arinest)
10299                         flags |= VSQUOTE;
10300                 *((char *)stackblock() + typeloc) = subtype | flags;
10301                 if (subtype != VSNORMAL) {
10302                         varnest++;
10303                         if (dblquote || arinest) {
10304                                 dqvarnest++;
10305                         }
10306                 }
10307         }
10308         goto parsesub_return;
10309 }
10310
10311 /*
10312  * Called to parse command substitutions.  Newstyle is set if the command
10313  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10314  * list of commands (passed by reference), and savelen is the number of
10315  * characters on the top of the stack which must be preserved.
10316  */
10317 parsebackq: {
10318         struct nodelist **nlpp;
10319         smallint savepbq;
10320         union node *n;
10321         char *volatile str;
10322         struct jmploc jmploc;
10323         struct jmploc *volatile savehandler;
10324         size_t savelen;
10325         smallint saveprompt = 0;
10326
10327 #ifdef __GNUC__
10328         (void) &saveprompt;
10329 #endif
10330         savepbq = parsebackquote;
10331         if (setjmp(jmploc.loc)) {
10332                 free(str);
10333                 parsebackquote = 0;
10334                 exception_handler = savehandler;
10335                 longjmp(exception_handler->loc, 1);
10336         }
10337         INT_OFF;
10338         str = NULL;
10339         savelen = out - (char *)stackblock();
10340         if (savelen > 0) {
10341                 str = ckmalloc(savelen);
10342                 memcpy(str, stackblock(), savelen);
10343         }
10344         savehandler = exception_handler;
10345         exception_handler = &jmploc;
10346         INT_ON;
10347         if (oldstyle) {
10348                 /* We must read until the closing backquote, giving special
10349                    treatment to some slashes, and then push the string and
10350                    reread it as input, interpreting it normally.  */
10351                 char *pout;
10352                 int pc;
10353                 size_t psavelen;
10354                 char *pstr;
10355
10356
10357                 STARTSTACKSTR(pout);
10358                 for (;;) {
10359                         if (needprompt) {
10360                                 setprompt(2);
10361                         }
10362                         pc = pgetc();
10363                         switch (pc) {
10364                         case '`':
10365                                 goto done;
10366
10367                         case '\\':
10368                                 pc = pgetc();
10369                                 if (pc == '\n') {
10370                                         plinno++;
10371                                         if (doprompt)
10372                                                 setprompt(2);
10373                                         /*
10374                                          * If eating a newline, avoid putting
10375                                          * the newline into the new character
10376                                          * stream (via the STPUTC after the
10377                                          * switch).
10378                                          */
10379                                         continue;
10380                                 }
10381                                 if (pc != '\\' && pc != '`' && pc != '$'
10382                                  && (!dblquote || pc != '"'))
10383                                         STPUTC('\\', pout);
10384                                 if (pc > PEOA_OR_PEOF) {
10385                                         break;
10386                                 }
10387                                 /* fall through */
10388
10389                         case PEOF:
10390 #if ENABLE_ASH_ALIAS
10391                         case PEOA:
10392 #endif
10393                                 startlinno = plinno;
10394                                 raise_error_syntax("EOF in backquote substitution");
10395
10396                         case '\n':
10397                                 plinno++;
10398                                 needprompt = doprompt;
10399                                 break;
10400
10401                         default:
10402                                 break;
10403                         }
10404                         STPUTC(pc, pout);
10405                 }
10406  done:
10407                 STPUTC('\0', pout);
10408                 psavelen = pout - (char *)stackblock();
10409                 if (psavelen > 0) {
10410                         pstr = grabstackstr(pout);
10411                         setinputstring(pstr);
10412                 }
10413         }
10414         nlpp = &bqlist;
10415         while (*nlpp)
10416                 nlpp = &(*nlpp)->next;
10417         *nlpp = stalloc(sizeof(**nlpp));
10418         (*nlpp)->next = NULL;
10419         parsebackquote = oldstyle;
10420
10421         if (oldstyle) {
10422                 saveprompt = doprompt;
10423                 doprompt = 0;
10424         }
10425
10426         n = list(2);
10427
10428         if (oldstyle)
10429                 doprompt = saveprompt;
10430         else if (readtoken() != TRP)
10431                 raise_error_unexpected_syntax(TRP);
10432
10433         (*nlpp)->n = n;
10434         if (oldstyle) {
10435                 /*
10436                  * Start reading from old file again, ignoring any pushed back
10437                  * tokens left from the backquote parsing
10438                  */
10439                 popfile();
10440                 tokpushback = 0;
10441         }
10442         while (stackblocksize() <= savelen)
10443                 growstackblock();
10444         STARTSTACKSTR(out);
10445         if (str) {
10446                 memcpy(out, str, savelen);
10447                 STADJUST(savelen, out);
10448                 INT_OFF;
10449                 free(str);
10450                 str = NULL;
10451                 INT_ON;
10452         }
10453         parsebackquote = savepbq;
10454         exception_handler = savehandler;
10455         if (arinest || dblquote)
10456                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10457         else
10458                 USTPUTC(CTLBACKQ, out);
10459         if (oldstyle)
10460                 goto parsebackq_oldreturn;
10461         goto parsebackq_newreturn;
10462 }
10463
10464 #if ENABLE_ASH_MATH_SUPPORT
10465 /*
10466  * Parse an arithmetic expansion (indicate start of one and set state)
10467  */
10468 parsearith: {
10469         if (++arinest == 1) {
10470                 prevsyntax = syntax;
10471                 syntax = ARISYNTAX;
10472                 USTPUTC(CTLARI, out);
10473                 if (dblquote)
10474                         USTPUTC('"', out);
10475                 else
10476                         USTPUTC(' ', out);
10477         } else {
10478                 /*
10479                  * we collapse embedded arithmetic expansion to
10480                  * parenthesis, which should be equivalent
10481                  */
10482                 USTPUTC('(', out);
10483         }
10484         goto parsearith_return;
10485 }
10486 #endif
10487
10488 } /* end of readtoken */
10489
10490 /*
10491  * Read the next input token.
10492  * If the token is a word, we set backquotelist to the list of cmds in
10493  *      backquotes.  We set quoteflag to true if any part of the word was
10494  *      quoted.
10495  * If the token is TREDIR, then we set redirnode to a structure containing
10496  *      the redirection.
10497  * In all cases, the variable startlinno is set to the number of the line
10498  *      on which the token starts.
10499  *
10500  * [Change comment:  here documents and internal procedures]
10501  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10502  *  word parsing code into a separate routine.  In this case, readtoken
10503  *  doesn't need to have any internal procedures, but parseword does.
10504  *  We could also make parseoperator in essence the main routine, and
10505  *  have parseword (readtoken1?) handle both words and redirection.]
10506  */
10507 #define NEW_xxreadtoken
10508 #ifdef NEW_xxreadtoken
10509 /* singles must be first! */
10510 static const char xxreadtoken_chars[7] ALIGN1 = {
10511         '\n', '(', ')', '&', '|', ';', 0
10512 };
10513
10514 static const char xxreadtoken_tokens[] ALIGN1 = {
10515         TNL, TLP, TRP,          /* only single occurrence allowed */
10516         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10517         TEOF,                   /* corresponds to trailing nul */
10518         TAND, TOR, TENDCASE     /* if double occurrence */
10519 };
10520
10521 #define xxreadtoken_doubles \
10522         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10523 #define xxreadtoken_singles \
10524         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10525
10526 static int
10527 xxreadtoken(void)
10528 {
10529         int c;
10530
10531         if (tokpushback) {
10532                 tokpushback = 0;
10533                 return lasttoken;
10534         }
10535         if (needprompt) {
10536                 setprompt(2);
10537         }
10538         startlinno = plinno;
10539         for (;;) {                      /* until token or start of word found */
10540                 c = pgetc_macro();
10541
10542                 if ((c != ' ') && (c != '\t')
10543 #if ENABLE_ASH_ALIAS
10544                  && (c != PEOA)
10545 #endif
10546                 ) {
10547                         if (c == '#') {
10548                                 while ((c = pgetc()) != '\n' && c != PEOF);
10549                                 pungetc();
10550                         } else if (c == '\\') {
10551                                 if (pgetc() != '\n') {
10552                                         pungetc();
10553                                         goto READTOKEN1;
10554                                 }
10555                                 startlinno = ++plinno;
10556                                 if (doprompt)
10557                                         setprompt(2);
10558                         } else {
10559                                 const char *p
10560                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10561
10562                                 if (c != PEOF) {
10563                                         if (c == '\n') {
10564                                                 plinno++;
10565                                                 needprompt = doprompt;
10566                                         }
10567
10568                                         p = strchr(xxreadtoken_chars, c);
10569                                         if (p == NULL) {
10570  READTOKEN1:
10571                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10572                                         }
10573
10574                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10575                                                 if (pgetc() == *p) {    /* double occurrence? */
10576                                                         p += xxreadtoken_doubles + 1;
10577                                                 } else {
10578                                                         pungetc();
10579                                                 }
10580                                         }
10581                                 }
10582                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10583                         }
10584                 }
10585         } /* for */
10586 }
10587 #else
10588 #define RETURN(token)   return lasttoken = token
10589 static int
10590 xxreadtoken(void)
10591 {
10592         int c;
10593
10594         if (tokpushback) {
10595                 tokpushback = 0;
10596                 return lasttoken;
10597         }
10598         if (needprompt) {
10599                 setprompt(2);
10600         }
10601         startlinno = plinno;
10602         for (;;) {      /* until token or start of word found */
10603                 c = pgetc_macro();
10604                 switch (c) {
10605                 case ' ': case '\t':
10606 #if ENABLE_ASH_ALIAS
10607                 case PEOA:
10608 #endif
10609                         continue;
10610                 case '#':
10611                         while ((c = pgetc()) != '\n' && c != PEOF);
10612                         pungetc();
10613                         continue;
10614                 case '\\':
10615                         if (pgetc() == '\n') {
10616                                 startlinno = ++plinno;
10617                                 if (doprompt)
10618                                         setprompt(2);
10619                                 continue;
10620                         }
10621                         pungetc();
10622                         goto breakloop;
10623                 case '\n':
10624                         plinno++;
10625                         needprompt = doprompt;
10626                         RETURN(TNL);
10627                 case PEOF:
10628                         RETURN(TEOF);
10629                 case '&':
10630                         if (pgetc() == '&')
10631                                 RETURN(TAND);
10632                         pungetc();
10633                         RETURN(TBACKGND);
10634                 case '|':
10635                         if (pgetc() == '|')
10636                                 RETURN(TOR);
10637                         pungetc();
10638                         RETURN(TPIPE);
10639                 case ';':
10640                         if (pgetc() == ';')
10641                                 RETURN(TENDCASE);
10642                         pungetc();
10643                         RETURN(TSEMI);
10644                 case '(':
10645                         RETURN(TLP);
10646                 case ')':
10647                         RETURN(TRP);
10648                 default:
10649                         goto breakloop;
10650                 }
10651         }
10652  breakloop:
10653         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10654 #undef RETURN
10655 }
10656 #endif /* NEW_xxreadtoken */
10657
10658 static int
10659 readtoken(void)
10660 {
10661         int t;
10662 #if DEBUG
10663         smallint alreadyseen = tokpushback;
10664 #endif
10665
10666 #if ENABLE_ASH_ALIAS
10667  top:
10668 #endif
10669
10670         t = xxreadtoken();
10671
10672         /*
10673          * eat newlines
10674          */
10675         if (checkkwd & CHKNL) {
10676                 while (t == TNL) {
10677                         parseheredoc();
10678                         t = xxreadtoken();
10679                 }
10680         }
10681
10682         if (t != TWORD || quoteflag) {
10683                 goto out;
10684         }
10685
10686         /*
10687          * check for keywords
10688          */
10689         if (checkkwd & CHKKWD) {
10690                 const char *const *pp;
10691
10692                 pp = findkwd(wordtext);
10693                 if (pp) {
10694                         lasttoken = t = pp - tokname_array;
10695                         TRACE(("keyword %s recognized\n", tokname(t)));
10696                         goto out;
10697                 }
10698         }
10699
10700         if (checkkwd & CHKALIAS) {
10701 #if ENABLE_ASH_ALIAS
10702                 struct alias *ap;
10703                 ap = lookupalias(wordtext, 1);
10704                 if (ap != NULL) {
10705                         if (*ap->val) {
10706                                 pushstring(ap->val, ap);
10707                         }
10708                         goto top;
10709                 }
10710 #endif
10711         }
10712  out:
10713         checkkwd = 0;
10714 #if DEBUG
10715         if (!alreadyseen)
10716                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10717         else
10718                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10719 #endif
10720         return t;
10721 }
10722
10723 static char
10724 peektoken(void)
10725 {
10726         int t;
10727
10728         t = readtoken();
10729         tokpushback = 1;
10730         return tokname_array[t][0];
10731 }
10732
10733 /*
10734  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
10735  * valid parse tree indicating a blank line.)
10736  */
10737 static union node *
10738 parsecmd(int interact)
10739 {
10740         int t;
10741
10742         tokpushback = 0;
10743         doprompt = interact;
10744         if (doprompt)
10745                 setprompt(doprompt);
10746         needprompt = 0;
10747         t = readtoken();
10748         if (t == TEOF)
10749                 return NEOF;
10750         if (t == TNL)
10751                 return NULL;
10752         tokpushback = 1;
10753         return list(1);
10754 }
10755
10756 /*
10757  * Input any here documents.
10758  */
10759 static void
10760 parseheredoc(void)
10761 {
10762         struct heredoc *here;
10763         union node *n;
10764
10765         here = heredoclist;
10766         heredoclist = 0;
10767
10768         while (here) {
10769                 if (needprompt) {
10770                         setprompt(2);
10771                 }
10772                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10773                                 here->eofmark, here->striptabs);
10774                 n = stalloc(sizeof(struct narg));
10775                 n->narg.type = NARG;
10776                 n->narg.next = NULL;
10777                 n->narg.text = wordtext;
10778                 n->narg.backquote = backquotelist;
10779                 here->here->nhere.doc = n;
10780                 here = here->next;
10781         }
10782 }
10783
10784
10785 /*
10786  * called by editline -- any expansions to the prompt should be added here.
10787  */
10788 #if ENABLE_ASH_EXPAND_PRMT
10789 static const char *
10790 expandstr(const char *ps)
10791 {
10792         union node n;
10793
10794         /* XXX Fix (char *) cast. */
10795         setinputstring((char *)ps);
10796         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
10797         popfile();
10798
10799         n.narg.type = NARG;
10800         n.narg.next = NULL;
10801         n.narg.text = wordtext;
10802         n.narg.backquote = backquotelist;
10803
10804         expandarg(&n, NULL, 0);
10805         return stackblock();
10806 }
10807 #endif
10808
10809 /*
10810  * Execute a command or commands contained in a string.
10811  */
10812 static int
10813 evalstring(char *s, int mask)
10814 {
10815         union node *n;
10816         struct stackmark smark;
10817         int skip;
10818
10819         setinputstring(s);
10820         setstackmark(&smark);
10821
10822         skip = 0;
10823         while ((n = parsecmd(0)) != NEOF) {
10824                 evaltree(n, 0);
10825                 popstackmark(&smark);
10826                 skip = evalskip;
10827                 if (skip)
10828                         break;
10829         }
10830         popfile();
10831
10832         skip &= mask;
10833         evalskip = skip;
10834         return skip;
10835 }
10836
10837 /*
10838  * The eval command.
10839  */
10840 static int
10841 evalcmd(int argc, char **argv)
10842 {
10843         char *p;
10844         char *concat;
10845         char **ap;
10846
10847         if (argc > 1) {
10848                 p = argv[1];
10849                 if (argc > 2) {
10850                         STARTSTACKSTR(concat);
10851                         ap = argv + 2;
10852                         for (;;) {
10853                                 concat = stack_putstr(p, concat);
10854                                 p = *ap++;
10855                                 if (p == NULL)
10856                                         break;
10857                                 STPUTC(' ', concat);
10858                         }
10859                         STPUTC('\0', concat);
10860                         p = grabstackstr(concat);
10861                 }
10862                 evalstring(p, ~SKIPEVAL);
10863
10864         }
10865         return exitstatus;
10866 }
10867
10868 /*
10869  * Read and execute commands.  "Top" is nonzero for the top level command
10870  * loop; it turns on prompting if the shell is interactive.
10871  */
10872 static int
10873 cmdloop(int top)
10874 {
10875         union node *n;
10876         struct stackmark smark;
10877         int inter;
10878         int numeof = 0;
10879
10880         TRACE(("cmdloop(%d) called\n", top));
10881         for (;;) {
10882                 int skip;
10883
10884                 setstackmark(&smark);
10885 #if JOBS
10886                 if (jobctl)
10887                         showjobs(stderr, SHOW_CHANGED);
10888 #endif
10889                 inter = 0;
10890                 if (iflag && top) {
10891                         inter++;
10892 #if ENABLE_ASH_MAIL
10893                         chkmail();
10894 #endif
10895                 }
10896                 n = parsecmd(inter);
10897                 /* showtree(n); DEBUG */
10898                 if (n == NEOF) {
10899                         if (!top || numeof >= 50)
10900                                 break;
10901                         if (!stoppedjobs()) {
10902                                 if (!Iflag)
10903                                         break;
10904                                 out2str("\nUse \"exit\" to leave shell.\n");
10905                         }
10906                         numeof++;
10907                 } else if (nflag == 0) {
10908                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
10909                         job_warning >>= 1;
10910                         numeof = 0;
10911                         evaltree(n, 0);
10912                 }
10913                 popstackmark(&smark);
10914                 skip = evalskip;
10915
10916                 if (skip) {
10917                         evalskip = 0;
10918                         return skip & SKIPEVAL;
10919                 }
10920         }
10921         return 0;
10922 }
10923
10924 /*
10925  * Take commands from a file.  To be compatible we should do a path
10926  * search for the file, which is necessary to find sub-commands.
10927  */
10928 static char *
10929 find_dot_file(char *name)
10930 {
10931         char *fullname;
10932         const char *path = pathval();
10933         struct stat statb;
10934
10935         /* don't try this for absolute or relative paths */
10936         if (strchr(name, '/'))
10937                 return name;
10938
10939         while ((fullname = padvance(&path, name)) != NULL) {
10940                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
10941                         /*
10942                          * Don't bother freeing here, since it will
10943                          * be freed by the caller.
10944                          */
10945                         return fullname;
10946                 }
10947                 stunalloc(fullname);
10948         }
10949
10950         /* not found in the PATH */
10951         ash_msg_and_raise_error("%s: not found", name);
10952         /* NOTREACHED */
10953 }
10954
10955 static int
10956 dotcmd(int argc, char **argv)
10957 {
10958         struct strlist *sp;
10959         volatile struct shparam saveparam;
10960         int status = 0;
10961
10962         for (sp = cmdenviron; sp; sp = sp->next)
10963                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10964
10965         if (argc >= 2) {        /* That's what SVR2 does */
10966                 char *fullname;
10967
10968                 fullname = find_dot_file(argv[1]);
10969
10970                 if (argc > 2) {
10971                         saveparam = shellparam;
10972                         shellparam.malloc = 0;
10973                         shellparam.nparam = argc - 2;
10974                         shellparam.p = argv + 2;
10975                 };
10976
10977                 setinputfile(fullname, INPUT_PUSH_FILE);
10978                 commandname = fullname;
10979                 cmdloop(0);
10980                 popfile();
10981
10982                 if (argc > 2) {
10983                         freeparam(&shellparam);
10984                         shellparam = saveparam;
10985                 };
10986                 status = exitstatus;
10987         }
10988         return status;
10989 }
10990
10991 static int
10992 exitcmd(int argc, char **argv)
10993 {
10994         if (stoppedjobs())
10995                 return 0;
10996         if (argc > 1)
10997                 exitstatus = number(argv[1]);
10998         raise_exception(EXEXIT);
10999         /* NOTREACHED */
11000 }
11001
11002 #if ENABLE_ASH_BUILTIN_ECHO
11003 static int
11004 echocmd(int argc, char **argv)
11005 {
11006         return echo_main(argc, argv);
11007 }
11008 #endif
11009
11010 #if ENABLE_ASH_BUILTIN_TEST
11011 static int
11012 testcmd(int argc, char **argv)
11013 {
11014         return test_main(argc, argv);
11015 }
11016 #endif
11017
11018 /*
11019  * Read a file containing shell functions.
11020  */
11021 static void
11022 readcmdfile(char *name)
11023 {
11024         setinputfile(name, INPUT_PUSH_FILE);
11025         cmdloop(0);
11026         popfile();
11027 }
11028
11029
11030 /* ============ find_command inplementation */
11031
11032 /*
11033  * Resolve a command name.  If you change this routine, you may have to
11034  * change the shellexec routine as well.
11035  */
11036 static void
11037 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11038 {
11039         struct tblentry *cmdp;
11040         int idx;
11041         int prev;
11042         char *fullname;
11043         struct stat statb;
11044         int e;
11045         int updatetbl;
11046         struct builtincmd *bcmd;
11047
11048         /* If name contains a slash, don't use PATH or hash table */
11049         if (strchr(name, '/') != NULL) {
11050                 entry->u.index = -1;
11051                 if (act & DO_ABS) {
11052                         while (stat(name, &statb) < 0) {
11053 #ifdef SYSV
11054                                 if (errno == EINTR)
11055                                         continue;
11056 #endif
11057                                 entry->cmdtype = CMDUNKNOWN;
11058                                 return;
11059                         }
11060                 }
11061                 entry->cmdtype = CMDNORMAL;
11062                 return;
11063         }
11064
11065 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11066
11067         updatetbl = (path == pathval());
11068         if (!updatetbl) {
11069                 act |= DO_ALTPATH;
11070                 if (strstr(path, "%builtin") != NULL)
11071                         act |= DO_ALTBLTIN;
11072         }
11073
11074         /* If name is in the table, check answer will be ok */
11075         cmdp = cmdlookup(name, 0);
11076         if (cmdp != NULL) {
11077                 int bit;
11078
11079                 switch (cmdp->cmdtype) {
11080                 default:
11081 #if DEBUG
11082                         abort();
11083 #endif
11084                 case CMDNORMAL:
11085                         bit = DO_ALTPATH;
11086                         break;
11087                 case CMDFUNCTION:
11088                         bit = DO_NOFUNC;
11089                         break;
11090                 case CMDBUILTIN:
11091                         bit = DO_ALTBLTIN;
11092                         break;
11093                 }
11094                 if (act & bit) {
11095                         updatetbl = 0;
11096                         cmdp = NULL;
11097                 } else if (cmdp->rehash == 0)
11098                         /* if not invalidated by cd, we're done */
11099                         goto success;
11100         }
11101
11102         /* If %builtin not in path, check for builtin next */
11103         bcmd = find_builtin(name);
11104         if (bcmd) {
11105                 if (IS_BUILTIN_REGULAR(bcmd))
11106                         goto builtin_success;
11107                 if (act & DO_ALTPATH) {
11108                         if (!(act & DO_ALTBLTIN))
11109                                 goto builtin_success;
11110                 } else if (builtinloc <= 0) {
11111                         goto builtin_success;
11112                 }
11113         }
11114
11115 #if ENABLE_FEATURE_SH_STANDALONE
11116         if (find_applet_by_name(name)) {
11117                 entry->cmdtype = CMDNORMAL;
11118                 entry->u.index = -1;
11119                 return;
11120         }
11121 #endif
11122
11123         /* We have to search path. */
11124         prev = -1;              /* where to start */
11125         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11126                 if (cmdp->cmdtype == CMDBUILTIN)
11127                         prev = builtinloc;
11128                 else
11129                         prev = cmdp->param.index;
11130         }
11131
11132         e = ENOENT;
11133         idx = -1;
11134  loop:
11135         while ((fullname = padvance(&path, name)) != NULL) {
11136                 stunalloc(fullname);
11137                 /* NB: code below will still use fullname
11138                  * despite it being "unallocated" */
11139                 idx++;
11140                 if (pathopt) {
11141                         if (prefix(pathopt, "builtin")) {
11142                                 if (bcmd)
11143                                         goto builtin_success;
11144                                 continue;
11145                         } else if (!(act & DO_NOFUNC)
11146                          && prefix(pathopt, "func")) {
11147                                 /* handled below */
11148                         } else {
11149                                 /* ignore unimplemented options */
11150                                 continue;
11151                         }
11152                 }
11153                 /* if rehash, don't redo absolute path names */
11154                 if (fullname[0] == '/' && idx <= prev) {
11155                         if (idx < prev)
11156                                 continue;
11157                         TRACE(("searchexec \"%s\": no change\n", name));
11158                         goto success;
11159                 }
11160                 while (stat(fullname, &statb) < 0) {
11161 #ifdef SYSV
11162                         if (errno == EINTR)
11163                                 continue;
11164 #endif
11165                         if (errno != ENOENT && errno != ENOTDIR)
11166                                 e = errno;
11167                         goto loop;
11168                 }
11169                 e = EACCES;     /* if we fail, this will be the error */
11170                 if (!S_ISREG(statb.st_mode))
11171                         continue;
11172                 if (pathopt) {          /* this is a %func directory */
11173                         stalloc(strlen(fullname) + 1);
11174                         /* NB: stalloc will return space pointed by fullname
11175                          * (because we don't have any intervening allocations
11176                          * between stunalloc above and this stalloc) */
11177                         readcmdfile(fullname);
11178                         cmdp = cmdlookup(name, 0);
11179                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11180                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11181                         stunalloc(fullname);
11182                         goto success;
11183                 }
11184                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11185                 if (!updatetbl) {
11186                         entry->cmdtype = CMDNORMAL;
11187                         entry->u.index = idx;
11188                         return;
11189                 }
11190                 INT_OFF;
11191                 cmdp = cmdlookup(name, 1);
11192                 cmdp->cmdtype = CMDNORMAL;
11193                 cmdp->param.index = idx;
11194                 INT_ON;
11195                 goto success;
11196         }
11197
11198         /* We failed.  If there was an entry for this command, delete it */
11199         if (cmdp && updatetbl)
11200                 delete_cmd_entry();
11201         if (act & DO_ERR)
11202                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11203         entry->cmdtype = CMDUNKNOWN;
11204         return;
11205
11206  builtin_success:
11207         if (!updatetbl) {
11208                 entry->cmdtype = CMDBUILTIN;
11209                 entry->u.cmd = bcmd;
11210                 return;
11211         }
11212         INT_OFF;
11213         cmdp = cmdlookup(name, 1);
11214         cmdp->cmdtype = CMDBUILTIN;
11215         cmdp->param.cmd = bcmd;
11216         INT_ON;
11217  success:
11218         cmdp->rehash = 0;
11219         entry->cmdtype = cmdp->cmdtype;
11220         entry->u = cmdp->param;
11221 }
11222
11223
11224 /* ============ trap.c */
11225
11226 /*
11227  * The trap builtin.
11228  */
11229 static int
11230 trapcmd(int argc, char **argv)
11231 {
11232         char *action;
11233         char **ap;
11234         int signo;
11235
11236         nextopt(nullstr);
11237         ap = argptr;
11238         if (!*ap) {
11239                 for (signo = 0; signo < NSIG; signo++) {
11240                         if (trap[signo] != NULL) {
11241                                 const char *sn;
11242
11243                                 sn = get_signame(signo);
11244                                 out1fmt("trap -- %s %s\n",
11245                                         single_quote(trap[signo]), sn);
11246                         }
11247                 }
11248                 return 0;
11249         }
11250         if (!ap[1])
11251                 action = NULL;
11252         else
11253                 action = *ap++;
11254         while (*ap) {
11255                 signo = get_signum(*ap);
11256                 if (signo < 0)
11257                         ash_msg_and_raise_error("%s: bad trap", *ap);
11258                 INT_OFF;
11259                 if (action) {
11260                         if (LONE_DASH(action))
11261                                 action = NULL;
11262                         else
11263                                 action = ckstrdup(action);
11264                 }
11265                 free(trap[signo]);
11266                 trap[signo] = action;
11267                 if (signo != 0)
11268                         setsignal(signo);
11269                 INT_ON;
11270                 ap++;
11271         }
11272         return 0;
11273 }
11274
11275
11276 /* ============ Builtins */
11277
11278 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11279 /*
11280  * Lists available builtins
11281  */
11282 static int
11283 helpcmd(int argc, char **argv)
11284 {
11285         int col, i;
11286
11287         out1fmt("\nBuilt-in commands:\n-------------------\n");
11288         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11289                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11290                                         builtintab[i].name + 1);
11291                 if (col > 60) {
11292                         out1fmt("\n");
11293                         col = 0;
11294                 }
11295         }
11296 #if ENABLE_FEATURE_SH_STANDALONE
11297         for (i = 0; i < NUM_APPLETS; i++) {
11298                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11299                 if (col > 60) {
11300                         out1fmt("\n");
11301                         col = 0;
11302                 }
11303         }
11304 #endif
11305         out1fmt("\n\n");
11306         return EXIT_SUCCESS;
11307 }
11308 #endif /* FEATURE_SH_EXTRA_QUIET */
11309
11310 /*
11311  * The export and readonly commands.
11312  */
11313 static int
11314 exportcmd(int argc, char **argv)
11315 {
11316         struct var *vp;
11317         char *name;
11318         const char *p;
11319         char **aptr;
11320         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11321
11322         if (nextopt("p") != 'p') {
11323                 aptr = argptr;
11324                 name = *aptr;
11325                 if (name) {
11326                         do {
11327                                 p = strchr(name, '=');
11328                                 if (p != NULL) {
11329                                         p++;
11330                                 } else {
11331                                         vp = *findvar(hashvar(name), name);
11332                                         if (vp) {
11333                                                 vp->flags |= flag;
11334                                                 continue;
11335                                         }
11336                                 }
11337                                 setvar(name, p, flag);
11338                         } while ((name = *++aptr) != NULL);
11339                         return 0;
11340                 }
11341         }
11342         showvars(argv[0], flag, 0);
11343         return 0;
11344 }
11345
11346 /*
11347  * Delete a function if it exists.
11348  */
11349 static void
11350 unsetfunc(const char *name)
11351 {
11352         struct tblentry *cmdp;
11353
11354         cmdp = cmdlookup(name, 0);
11355         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11356                 delete_cmd_entry();
11357 }
11358
11359 /*
11360  * The unset builtin command.  We unset the function before we unset the
11361  * variable to allow a function to be unset when there is a readonly variable
11362  * with the same name.
11363  */
11364 static int
11365 unsetcmd(int argc, char **argv)
11366 {
11367         char **ap;
11368         int i;
11369         int flag = 0;
11370         int ret = 0;
11371
11372         while ((i = nextopt("vf")) != '\0') {
11373                 flag = i;
11374         }
11375
11376         for (ap = argptr; *ap; ap++) {
11377                 if (flag != 'f') {
11378                         i = unsetvar(*ap);
11379                         ret |= i;
11380                         if (!(i & 2))
11381                                 continue;
11382                 }
11383                 if (flag != 'v')
11384                         unsetfunc(*ap);
11385         }
11386         return ret & 1;
11387 }
11388
11389
11390 /*      setmode.c      */
11391
11392 #include <sys/times.h>
11393
11394 static const unsigned char timescmd_str[] ALIGN1 = {
11395         ' ',  offsetof(struct tms, tms_utime),
11396         '\n', offsetof(struct tms, tms_stime),
11397         ' ',  offsetof(struct tms, tms_cutime),
11398         '\n', offsetof(struct tms, tms_cstime),
11399         0
11400 };
11401
11402 static int
11403 timescmd(int ac, char **av)
11404 {
11405         long clk_tck, s, t;
11406         const unsigned char *p;
11407         struct tms buf;
11408
11409         clk_tck = sysconf(_SC_CLK_TCK);
11410         times(&buf);
11411
11412         p = timescmd_str;
11413         do {
11414                 t = *(clock_t *)(((char *) &buf) + p[1]);
11415                 s = t / clk_tck;
11416                 out1fmt("%ldm%ld.%.3lds%c",
11417                         s/60, s%60,
11418                         ((t - s * clk_tck) * 1000) / clk_tck,
11419                         p[0]);
11420         } while (*(p += 2));
11421
11422         return 0;
11423 }
11424
11425 #if ENABLE_ASH_MATH_SUPPORT
11426 static arith_t
11427 dash_arith(const char *s)
11428 {
11429         arith_t result;
11430         int errcode = 0;
11431
11432         INT_OFF;
11433         result = arith(s, &errcode);
11434         if (errcode < 0) {
11435                 if (errcode == -3)
11436                         ash_msg_and_raise_error("exponent less than 0");
11437                 if (errcode == -2)
11438                         ash_msg_and_raise_error("divide by zero");
11439                 if (errcode == -5)
11440                         ash_msg_and_raise_error("expression recursion loop detected");
11441                 raise_error_syntax(s);
11442         }
11443         INT_ON;
11444
11445         return result;
11446 }
11447
11448 /*
11449  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11450  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11451  *
11452  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11453  */
11454 static int
11455 letcmd(int argc, char **argv)
11456 {
11457         char **ap;
11458         arith_t i = 0;
11459
11460         ap = argv + 1;
11461         if (!*ap)
11462                 ash_msg_and_raise_error("expression expected");
11463         for (ap = argv + 1; *ap; ap++) {
11464                 i = dash_arith(*ap);
11465         }
11466
11467         return !i;
11468 }
11469 #endif /* ASH_MATH_SUPPORT */
11470
11471
11472 /* ============ miscbltin.c
11473  *
11474  * Miscellaneous builtins.
11475  */
11476
11477 #undef rflag
11478
11479 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11480 typedef enum __rlimit_resource rlim_t;
11481 #endif
11482
11483 /*
11484  * The read builtin.  The -e option causes backslashes to escape the
11485  * following character.
11486  *
11487  * This uses unbuffered input, which may be avoidable in some cases.
11488  */
11489 static int
11490 readcmd(int argc, char **argv)
11491 {
11492         char **ap;
11493         int backslash;
11494         char c;
11495         int rflag;
11496         char *prompt;
11497         const char *ifs;
11498         char *p;
11499         int startword;
11500         int status;
11501         int i;
11502 #if ENABLE_ASH_READ_NCHARS
11503         int n_flag = 0;
11504         int nchars = 0;
11505         int silent = 0;
11506         struct termios tty, old_tty;
11507 #endif
11508 #if ENABLE_ASH_READ_TIMEOUT
11509         fd_set set;
11510         struct timeval ts;
11511
11512         ts.tv_sec = ts.tv_usec = 0;
11513 #endif
11514
11515         rflag = 0;
11516         prompt = NULL;
11517 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11518         while ((i = nextopt("p:rt:n:s")) != '\0')
11519 #elif ENABLE_ASH_READ_NCHARS
11520         while ((i = nextopt("p:rn:s")) != '\0')
11521 #elif ENABLE_ASH_READ_TIMEOUT
11522         while ((i = nextopt("p:rt:")) != '\0')
11523 #else
11524         while ((i = nextopt("p:r")) != '\0')
11525 #endif
11526         {
11527                 switch (i) {
11528                 case 'p':
11529                         prompt = optionarg;
11530                         break;
11531 #if ENABLE_ASH_READ_NCHARS
11532                 case 'n':
11533                         nchars = bb_strtou(optionarg, NULL, 10);
11534                         if (nchars < 0 || errno)
11535                                 ash_msg_and_raise_error("invalid count");
11536                         n_flag = nchars; /* just a flag "nchars is nonzero" */
11537                         break;
11538                 case 's':
11539                         silent = 1;
11540                         break;
11541 #endif
11542 #if ENABLE_ASH_READ_TIMEOUT
11543                 case 't':
11544                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
11545                         ts.tv_usec = 0;
11546                         /* EINVAL means number is ok, but not terminated by NUL */
11547                         if (*p == '.' && errno == EINVAL) {
11548                                 char *p2;
11549                                 if (*++p) {
11550                                         int scale;
11551                                         ts.tv_usec = bb_strtou(p, &p2, 10);
11552                                         if (errno)
11553                                                 ash_msg_and_raise_error("invalid timeout");
11554                                         scale = p2 - p;
11555                                         /* normalize to usec */
11556                                         if (scale > 6)
11557                                                 ash_msg_and_raise_error("invalid timeout");
11558                                         while (scale++ < 6)
11559                                                 ts.tv_usec *= 10;
11560                                 }
11561                         } else if (ts.tv_sec < 0 || errno) {
11562                                 ash_msg_and_raise_error("invalid timeout");
11563                         }
11564                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
11565                                 ash_msg_and_raise_error("invalid timeout");
11566                         }
11567                         break;
11568 #endif
11569                 case 'r':
11570                         rflag = 1;
11571                         break;
11572                 default:
11573                         break;
11574                 }
11575         }
11576         if (prompt && isatty(0)) {
11577                 out2str(prompt);
11578         }
11579         ap = argptr;
11580         if (*ap == NULL)
11581                 ash_msg_and_raise_error("arg count");
11582         ifs = bltinlookup("IFS");
11583         if (ifs == NULL)
11584                 ifs = defifs;
11585 #if ENABLE_ASH_READ_NCHARS
11586         if (n_flag || silent) {
11587                 if (tcgetattr(0, &tty) != 0) {
11588                         /* Not a tty */
11589                         n_flag = 0;
11590                         silent = 0;
11591                 } else {
11592                         old_tty = tty;
11593                         if (n_flag) {
11594                                 tty.c_lflag &= ~ICANON;
11595                                 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
11596                         }
11597                         if (silent) {
11598                                 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
11599                         }
11600                         tcsetattr(0, TCSANOW, &tty);
11601                 }
11602         }
11603 #endif
11604 #if ENABLE_ASH_READ_TIMEOUT
11605         if (ts.tv_sec || ts.tv_usec) {
11606                 FD_ZERO(&set);
11607                 FD_SET(0, &set);
11608
11609                 /* poll-based wait produces bigger code, using select */
11610                 i = select(1, &set, NULL, NULL, &ts);
11611                 if (!i) { /* timed out! */
11612 #if ENABLE_ASH_READ_NCHARS
11613                         if (n_flag)
11614                                 tcsetattr(0, TCSANOW, &old_tty);
11615 #endif
11616                         return 1;
11617                 }
11618         }
11619 #endif
11620         status = 0;
11621         startword = 1;
11622         backslash = 0;
11623         STARTSTACKSTR(p);
11624         do {
11625                 if (read(0, &c, 1) != 1) {
11626                         status = 1;
11627                         break;
11628                 }
11629                 if (c == '\0')
11630                         continue;
11631                 if (backslash) {
11632                         backslash = 0;
11633                         if (c != '\n')
11634                                 goto put;
11635                         continue;
11636                 }
11637                 if (!rflag && c == '\\') {
11638                         backslash++;
11639                         continue;
11640                 }
11641                 if (c == '\n')
11642                         break;
11643                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11644                         continue;
11645                 }
11646                 startword = 0;
11647                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11648                         STACKSTRNUL(p);
11649                         setvar(*ap, stackblock(), 0);
11650                         ap++;
11651                         startword = 1;
11652                         STARTSTACKSTR(p);
11653                 } else {
11654  put:
11655                         STPUTC(c, p);
11656                 }
11657         }
11658 /* end of do {} while: */
11659 #if ENABLE_ASH_READ_NCHARS
11660         while (!n_flag || --nchars);
11661 #else
11662         while (1);
11663 #endif
11664
11665 #if ENABLE_ASH_READ_NCHARS
11666         if (n_flag || silent)
11667                 tcsetattr(0, TCSANOW, &old_tty);
11668 #endif
11669
11670         STACKSTRNUL(p);
11671         /* Remove trailing blanks */
11672         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11673                 *p = '\0';
11674         setvar(*ap, stackblock(), 0);
11675         while (*++ap != NULL)
11676                 setvar(*ap, nullstr, 0);
11677         return status;
11678 }
11679
11680 static int
11681 umaskcmd(int argc, char **argv)
11682 {
11683         static const char permuser[3] ALIGN1 = "ugo";
11684         static const char permmode[3] ALIGN1 = "rwx";
11685         static const short permmask[] ALIGN2 = {
11686                 S_IRUSR, S_IWUSR, S_IXUSR,
11687                 S_IRGRP, S_IWGRP, S_IXGRP,
11688                 S_IROTH, S_IWOTH, S_IXOTH
11689         };
11690
11691         char *ap;
11692         mode_t mask;
11693         int i;
11694         int symbolic_mode = 0;
11695
11696         while (nextopt("S") != '\0') {
11697                 symbolic_mode = 1;
11698         }
11699
11700         INT_OFF;
11701         mask = umask(0);
11702         umask(mask);
11703         INT_ON;
11704
11705         ap = *argptr;
11706         if (ap == NULL) {
11707                 if (symbolic_mode) {
11708                         char buf[18];
11709                         char *p = buf;
11710
11711                         for (i = 0; i < 3; i++) {
11712                                 int j;
11713
11714                                 *p++ = permuser[i];
11715                                 *p++ = '=';
11716                                 for (j = 0; j < 3; j++) {
11717                                         if ((mask & permmask[3 * i + j]) == 0) {
11718                                                 *p++ = permmode[j];
11719                                         }
11720                                 }
11721                                 *p++ = ',';
11722                         }
11723                         *--p = 0;
11724                         puts(buf);
11725                 } else {
11726                         out1fmt("%.4o\n", mask);
11727                 }
11728         } else {
11729                 if (isdigit((unsigned char) *ap)) {
11730                         mask = 0;
11731                         do {
11732                                 if (*ap >= '8' || *ap < '0')
11733                                         ash_msg_and_raise_error(illnum, argv[1]);
11734                                 mask = (mask << 3) + (*ap - '0');
11735                         } while (*++ap != '\0');
11736                         umask(mask);
11737                 } else {
11738                         mask = ~mask & 0777;
11739                         if (!bb_parse_mode(ap, &mask)) {
11740                                 ash_msg_and_raise_error("illegal mode: %s", ap);
11741                         }
11742                         umask(~mask & 0777);
11743                 }
11744         }
11745         return 0;
11746 }
11747
11748 /*
11749  * ulimit builtin
11750  *
11751  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11752  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11753  * ash by J.T. Conklin.
11754  *
11755  * Public domain.
11756  */
11757
11758 struct limits {
11759         uint8_t cmd;          /* RLIMIT_xxx fit into it */
11760         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
11761         char    option;
11762 };
11763
11764 static const struct limits limits_tbl[] = {
11765 #ifdef RLIMIT_CPU
11766         { RLIMIT_CPU,        0, 't' },
11767 #endif
11768 #ifdef RLIMIT_FSIZE
11769         { RLIMIT_FSIZE,      9, 'f' },
11770 #endif
11771 #ifdef RLIMIT_DATA
11772         { RLIMIT_DATA,      10, 'd' },
11773 #endif
11774 #ifdef RLIMIT_STACK
11775         { RLIMIT_STACK,     10, 's' },
11776 #endif
11777 #ifdef RLIMIT_CORE
11778         { RLIMIT_CORE,       9, 'c' },
11779 #endif
11780 #ifdef RLIMIT_RSS
11781         { RLIMIT_RSS,       10, 'm' },
11782 #endif
11783 #ifdef RLIMIT_MEMLOCK
11784         { RLIMIT_MEMLOCK,   10, 'l' },
11785 #endif
11786 #ifdef RLIMIT_NPROC
11787         { RLIMIT_NPROC,      0, 'p' },
11788 #endif
11789 #ifdef RLIMIT_NOFILE
11790         { RLIMIT_NOFILE,     0, 'n' },
11791 #endif
11792 #ifdef RLIMIT_AS
11793         { RLIMIT_AS,        10, 'v' },
11794 #endif
11795 #ifdef RLIMIT_LOCKS
11796         { RLIMIT_LOCKS,      0, 'w' },
11797 #endif
11798 };
11799 static const char limits_name[] =
11800 #ifdef RLIMIT_CPU
11801         "time(seconds)" "\0"
11802 #endif
11803 #ifdef RLIMIT_FSIZE
11804         "file(blocks)" "\0"
11805 #endif
11806 #ifdef RLIMIT_DATA
11807         "data(kb)" "\0"
11808 #endif
11809 #ifdef RLIMIT_STACK
11810         "stack(kb)" "\0"
11811 #endif
11812 #ifdef RLIMIT_CORE
11813         "coredump(blocks)" "\0"
11814 #endif
11815 #ifdef RLIMIT_RSS
11816         "memory(kb)" "\0"
11817 #endif
11818 #ifdef RLIMIT_MEMLOCK
11819         "locked memory(kb)" "\0"
11820 #endif
11821 #ifdef RLIMIT_NPROC
11822         "process" "\0"
11823 #endif
11824 #ifdef RLIMIT_NOFILE
11825         "nofiles" "\0"
11826 #endif
11827 #ifdef RLIMIT_AS
11828         "vmemory(kb)" "\0"
11829 #endif
11830 #ifdef RLIMIT_LOCKS
11831         "locks" "\0"
11832 #endif
11833 ;
11834
11835 enum limtype { SOFT = 0x1, HARD = 0x2 };
11836
11837 static void
11838 printlim(enum limtype how, const struct rlimit *limit,
11839                         const struct limits *l)
11840 {
11841         rlim_t val;
11842
11843         val = limit->rlim_max;
11844         if (how & SOFT)
11845                 val = limit->rlim_cur;
11846
11847         if (val == RLIM_INFINITY)
11848                 out1fmt("unlimited\n");
11849         else {
11850                 val >>= l->factor_shift;
11851                 out1fmt("%lld\n", (long long) val);
11852         }
11853 }
11854
11855 static int
11856 ulimitcmd(int argc, char **argv)
11857 {
11858         int c;
11859         rlim_t val = 0;
11860         enum limtype how = SOFT | HARD;
11861         const struct limits *l;
11862         int set, all = 0;
11863         int optc, what;
11864         struct rlimit limit;
11865
11866         what = 'f';
11867         while ((optc = nextopt("HSa"
11868 #ifdef RLIMIT_CPU
11869                                 "t"
11870 #endif
11871 #ifdef RLIMIT_FSIZE
11872                                 "f"
11873 #endif
11874 #ifdef RLIMIT_DATA
11875                                 "d"
11876 #endif
11877 #ifdef RLIMIT_STACK
11878                                 "s"
11879 #endif
11880 #ifdef RLIMIT_CORE
11881                                 "c"
11882 #endif
11883 #ifdef RLIMIT_RSS
11884                                 "m"
11885 #endif
11886 #ifdef RLIMIT_MEMLOCK
11887                                 "l"
11888 #endif
11889 #ifdef RLIMIT_NPROC
11890                                 "p"
11891 #endif
11892 #ifdef RLIMIT_NOFILE
11893                                 "n"
11894 #endif
11895 #ifdef RLIMIT_AS
11896                                 "v"
11897 #endif
11898 #ifdef RLIMIT_LOCKS
11899                                 "w"
11900 #endif
11901                                         )) != '\0')
11902                 switch (optc) {
11903                 case 'H':
11904                         how = HARD;
11905                         break;
11906                 case 'S':
11907                         how = SOFT;
11908                         break;
11909                 case 'a':
11910                         all = 1;
11911                         break;
11912                 default:
11913                         what = optc;
11914                 }
11915
11916         for (l = limits_tbl; l->option != what; l++)
11917                 continue;
11918
11919         set = *argptr ? 1 : 0;
11920         if (set) {
11921                 char *p = *argptr;
11922
11923                 if (all || argptr[1])
11924                         ash_msg_and_raise_error("too many arguments");
11925                 if (strncmp(p, "unlimited\n", 9) == 0)
11926                         val = RLIM_INFINITY;
11927                 else {
11928                         val = (rlim_t) 0;
11929
11930                         while ((c = *p++) >= '0' && c <= '9') {
11931                                 val = (val * 10) + (long)(c - '0');
11932                                 if (val < (rlim_t) 0)
11933                                         break;
11934                         }
11935                         if (c)
11936                                 ash_msg_and_raise_error("bad number");
11937                         val <<= l->factor_shift;
11938                 }
11939         }
11940         if (all) {
11941                 const char *lname = limits_name;
11942                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
11943                         getrlimit(l->cmd, &limit);
11944                         out1fmt("%-20s ", lname);
11945                         lname += strlen(lname) + 1;
11946                         printlim(how, &limit, l);
11947                 }
11948                 return 0;
11949         }
11950
11951         getrlimit(l->cmd, &limit);
11952         if (set) {
11953                 if (how & HARD)
11954                         limit.rlim_max = val;
11955                 if (how & SOFT)
11956                         limit.rlim_cur = val;
11957                 if (setrlimit(l->cmd, &limit) < 0)
11958                         ash_msg_and_raise_error("error setting limit (%m)");
11959         } else {
11960                 printlim(how, &limit, l);
11961         }
11962         return 0;
11963 }
11964
11965
11966 /* ============ Math support */
11967
11968 #if ENABLE_ASH_MATH_SUPPORT
11969
11970 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
11971
11972    Permission is hereby granted, free of charge, to any person obtaining
11973    a copy of this software and associated documentation files (the
11974    "Software"), to deal in the Software without restriction, including
11975    without limitation the rights to use, copy, modify, merge, publish,
11976    distribute, sublicense, and/or sell copies of the Software, and to
11977    permit persons to whom the Software is furnished to do so, subject to
11978    the following conditions:
11979
11980    The above copyright notice and this permission notice shall be
11981    included in all copies or substantial portions of the Software.
11982
11983    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11984    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11985    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11986    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
11987    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11988    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11989    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11990 */
11991
11992 /* This is my infix parser/evaluator. It is optimized for size, intended
11993  * as a replacement for yacc-based parsers. However, it may well be faster
11994  * than a comparable parser written in yacc. The supported operators are
11995  * listed in #defines below. Parens, order of operations, and error handling
11996  * are supported. This code is thread safe. The exact expression format should
11997  * be that which POSIX specifies for shells. */
11998
11999 /* The code uses a simple two-stack algorithm. See
12000  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12001  * for a detailed explanation of the infix-to-postfix algorithm on which
12002  * this is based (this code differs in that it applies operators immediately
12003  * to the stack instead of adding them to a queue to end up with an
12004  * expression). */
12005
12006 /* To use the routine, call it with an expression string and error return
12007  * pointer */
12008
12009 /*
12010  * Aug 24, 2001              Manuel Novoa III
12011  *
12012  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12013  *
12014  * 1) In arith_apply():
12015  *    a) Cached values of *numptr and &(numptr[-1]).
12016  *    b) Removed redundant test for zero denominator.
12017  *
12018  * 2) In arith():
12019  *    a) Eliminated redundant code for processing operator tokens by moving
12020  *       to a table-based implementation.  Also folded handling of parens
12021  *       into the table.
12022  *    b) Combined all 3 loops which called arith_apply to reduce generated
12023  *       code size at the cost of speed.
12024  *
12025  * 3) The following expressions were treated as valid by the original code:
12026  *       1()  ,    0!  ,    1 ( *3 )   .
12027  *    These bugs have been fixed by internally enclosing the expression in
12028  *    parens and then checking that all binary ops and right parens are
12029  *    preceded by a valid expression (NUM_TOKEN).
12030  *
12031  * Note: It may be desirable to replace Aaron's test for whitespace with
12032  * ctype's isspace() if it is used by another busybox applet or if additional
12033  * whitespace chars should be considered.  Look below the "#include"s for a
12034  * precompiler test.
12035  */
12036
12037 /*
12038  * Aug 26, 2001              Manuel Novoa III
12039  *
12040  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12041  *
12042  * Merge in Aaron's comments previously posted to the busybox list,
12043  * modified slightly to take account of my changes to the code.
12044  *
12045  */
12046
12047 /*
12048  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12049  *
12050  * - allow access to variable,
12051  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12052  * - realize assign syntax (VAR=expr, +=, *= etc)
12053  * - realize exponentiation (** operator)
12054  * - realize comma separated - expr, expr
12055  * - realise ++expr --expr expr++ expr--
12056  * - realise expr ? expr : expr (but, second expr calculate always)
12057  * - allow hexadecimal and octal numbers
12058  * - was restored loses XOR operator
12059  * - remove one goto label, added three ;-)
12060  * - protect $((num num)) as true zero expr (Manuel`s error)
12061  * - always use special isspace(), see comment from bash ;-)
12062  */
12063
12064 #define arith_isspace(arithval) \
12065         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12066
12067 typedef unsigned char operator;
12068
12069 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12070  * precedence, and 3 high bits are an ID unique across operators of that
12071  * precedence. The ID portion is so that multiple operators can have the
12072  * same precedence, ensuring that the leftmost one is evaluated first.
12073  * Consider * and /. */
12074
12075 #define tok_decl(prec,id) (((id)<<5)|(prec))
12076 #define PREC(op) ((op) & 0x1F)
12077
12078 #define TOK_LPAREN tok_decl(0,0)
12079
12080 #define TOK_COMMA tok_decl(1,0)
12081
12082 #define TOK_ASSIGN tok_decl(2,0)
12083 #define TOK_AND_ASSIGN tok_decl(2,1)
12084 #define TOK_OR_ASSIGN tok_decl(2,2)
12085 #define TOK_XOR_ASSIGN tok_decl(2,3)
12086 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12087 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12088 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12089 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12090
12091 #define TOK_MUL_ASSIGN tok_decl(3,0)
12092 #define TOK_DIV_ASSIGN tok_decl(3,1)
12093 #define TOK_REM_ASSIGN tok_decl(3,2)
12094
12095 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12096 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12097
12098 /* conditional is right associativity too */
12099 #define TOK_CONDITIONAL tok_decl(4,0)
12100 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12101
12102 #define TOK_OR tok_decl(5,0)
12103
12104 #define TOK_AND tok_decl(6,0)
12105
12106 #define TOK_BOR tok_decl(7,0)
12107
12108 #define TOK_BXOR tok_decl(8,0)
12109
12110 #define TOK_BAND tok_decl(9,0)
12111
12112 #define TOK_EQ tok_decl(10,0)
12113 #define TOK_NE tok_decl(10,1)
12114
12115 #define TOK_LT tok_decl(11,0)
12116 #define TOK_GT tok_decl(11,1)
12117 #define TOK_GE tok_decl(11,2)
12118 #define TOK_LE tok_decl(11,3)
12119
12120 #define TOK_LSHIFT tok_decl(12,0)
12121 #define TOK_RSHIFT tok_decl(12,1)
12122
12123 #define TOK_ADD tok_decl(13,0)
12124 #define TOK_SUB tok_decl(13,1)
12125
12126 #define TOK_MUL tok_decl(14,0)
12127 #define TOK_DIV tok_decl(14,1)
12128 #define TOK_REM tok_decl(14,2)
12129
12130 /* exponent is right associativity */
12131 #define TOK_EXPONENT tok_decl(15,1)
12132
12133 /* For now unary operators. */
12134 #define UNARYPREC 16
12135 #define TOK_BNOT tok_decl(UNARYPREC,0)
12136 #define TOK_NOT tok_decl(UNARYPREC,1)
12137
12138 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12139 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12140
12141 #define PREC_PRE (UNARYPREC+2)
12142
12143 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12144 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12145
12146 #define PREC_POST (UNARYPREC+3)
12147
12148 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12149 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12150
12151 #define SPEC_PREC (UNARYPREC+4)
12152
12153 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12154 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12155
12156 #define NUMPTR (*numstackptr)
12157
12158 static int
12159 tok_have_assign(operator op)
12160 {
12161         operator prec = PREC(op);
12162
12163         convert_prec_is_assing(prec);
12164         return (prec == PREC(TOK_ASSIGN) ||
12165                         prec == PREC_PRE || prec == PREC_POST);
12166 }
12167
12168 static int
12169 is_right_associativity(operator prec)
12170 {
12171         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12172                 || prec == PREC(TOK_CONDITIONAL));
12173 }
12174
12175 typedef struct ARITCH_VAR_NUM {
12176         arith_t val;
12177         arith_t contidional_second_val;
12178         char contidional_second_val_initialized;
12179         char *var;      /* if NULL then is regular number,
12180                            else is variable name */
12181 } v_n_t;
12182
12183 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12184         const char *var;
12185         struct CHK_VAR_RECURSIVE_LOOPED *next;
12186 } chk_var_recursive_looped_t;
12187
12188 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12189
12190 static int
12191 arith_lookup_val(v_n_t *t)
12192 {
12193         if (t->var) {
12194                 const char * p = lookupvar(t->var);
12195
12196                 if (p) {
12197                         int errcode;
12198
12199                         /* recursive try as expression */
12200                         chk_var_recursive_looped_t *cur;
12201                         chk_var_recursive_looped_t cur_save;
12202
12203                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12204                                 if (strcmp(cur->var, t->var) == 0) {
12205                                         /* expression recursion loop detected */
12206                                         return -5;
12207                                 }
12208                         }
12209                         /* save current lookuped var name */
12210                         cur = prev_chk_var_recursive;
12211                         cur_save.var = t->var;
12212                         cur_save.next = cur;
12213                         prev_chk_var_recursive = &cur_save;
12214
12215                         t->val = arith (p, &errcode);
12216                         /* restore previous ptr after recursiving */
12217                         prev_chk_var_recursive = cur;
12218                         return errcode;
12219                 }
12220                 /* allow undefined var as 0 */
12221                 t->val = 0;
12222         }
12223         return 0;
12224 }
12225
12226 /* "applying" a token means performing it on the top elements on the integer
12227  * stack. For a unary operator it will only change the top element, but a
12228  * binary operator will pop two arguments and push a result */
12229 static int
12230 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12231 {
12232         v_n_t *numptr_m1;
12233         arith_t numptr_val, rez;
12234         int ret_arith_lookup_val;
12235
12236         /* There is no operator that can work without arguments */
12237         if (NUMPTR == numstack) goto err;
12238         numptr_m1 = NUMPTR - 1;
12239
12240         /* check operand is var with noninteger value */
12241         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12242         if (ret_arith_lookup_val)
12243                 return ret_arith_lookup_val;
12244
12245         rez = numptr_m1->val;
12246         if (op == TOK_UMINUS)
12247                 rez *= -1;
12248         else if (op == TOK_NOT)
12249                 rez = !rez;
12250         else if (op == TOK_BNOT)
12251                 rez = ~rez;
12252         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12253                 rez++;
12254         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12255                 rez--;
12256         else if (op != TOK_UPLUS) {
12257                 /* Binary operators */
12258
12259                 /* check and binary operators need two arguments */
12260                 if (numptr_m1 == numstack) goto err;
12261
12262                 /* ... and they pop one */
12263                 --NUMPTR;
12264                 numptr_val = rez;
12265                 if (op == TOK_CONDITIONAL) {
12266                         if (! numptr_m1->contidional_second_val_initialized) {
12267                                 /* protect $((expr1 ? expr2)) without ": expr" */
12268                                 goto err;
12269                         }
12270                         rez = numptr_m1->contidional_second_val;
12271                 } else if (numptr_m1->contidional_second_val_initialized) {
12272                         /* protect $((expr1 : expr2)) without "expr ? " */
12273                         goto err;
12274                 }
12275                 numptr_m1 = NUMPTR - 1;
12276                 if (op != TOK_ASSIGN) {
12277                         /* check operand is var with noninteger value for not '=' */
12278                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12279                         if (ret_arith_lookup_val)
12280                                 return ret_arith_lookup_val;
12281                 }
12282                 if (op == TOK_CONDITIONAL) {
12283                         numptr_m1->contidional_second_val = rez;
12284                 }
12285                 rez = numptr_m1->val;
12286                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12287                         rez |= numptr_val;
12288                 else if (op == TOK_OR)
12289                         rez = numptr_val || rez;
12290                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12291                         rez &= numptr_val;
12292                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12293                         rez ^= numptr_val;
12294                 else if (op == TOK_AND)
12295                         rez = rez && numptr_val;
12296                 else if (op == TOK_EQ)
12297                         rez = (rez == numptr_val);
12298                 else if (op == TOK_NE)
12299                         rez = (rez != numptr_val);
12300                 else if (op == TOK_GE)
12301                         rez = (rez >= numptr_val);
12302                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12303                         rez >>= numptr_val;
12304                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12305                         rez <<= numptr_val;
12306                 else if (op == TOK_GT)
12307                         rez = (rez > numptr_val);
12308                 else if (op == TOK_LT)
12309                         rez = (rez < numptr_val);
12310                 else if (op == TOK_LE)
12311                         rez = (rez <= numptr_val);
12312                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12313                         rez *= numptr_val;
12314                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12315                         rez += numptr_val;
12316                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12317                         rez -= numptr_val;
12318                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12319                         rez = numptr_val;
12320                 else if (op == TOK_CONDITIONAL_SEP) {
12321                         if (numptr_m1 == numstack) {
12322                                 /* protect $((expr : expr)) without "expr ? " */
12323                                 goto err;
12324                         }
12325                         numptr_m1->contidional_second_val_initialized = op;
12326                         numptr_m1->contidional_second_val = numptr_val;
12327                 } else if (op == TOK_CONDITIONAL) {
12328                         rez = rez ?
12329                                 numptr_val : numptr_m1->contidional_second_val;
12330                 } else if (op == TOK_EXPONENT) {
12331                         if (numptr_val < 0)
12332                                 return -3;      /* exponent less than 0 */
12333                         else {
12334                                 arith_t c = 1;
12335
12336                                 if (numptr_val)
12337                                         while (numptr_val--)
12338                                                 c *= rez;
12339                                 rez = c;
12340                         }
12341                 } else if (numptr_val==0)          /* zero divisor check */
12342                         return -2;
12343                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12344                         rez /= numptr_val;
12345                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12346                         rez %= numptr_val;
12347         }
12348         if (tok_have_assign(op)) {
12349                 char buf[sizeof(arith_t_type)*3 + 2];
12350
12351                 if (numptr_m1->var == NULL) {
12352                         /* Hmm, 1=2 ? */
12353                         goto err;
12354                 }
12355                 /* save to shell variable */
12356 #if ENABLE_ASH_MATH_SUPPORT_64
12357                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12358 #else
12359                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12360 #endif
12361                 setvar(numptr_m1->var, buf, 0);
12362                 /* after saving, make previous value for v++ or v-- */
12363                 if (op == TOK_POST_INC)
12364                         rez--;
12365                 else if (op == TOK_POST_DEC)
12366                         rez++;
12367         }
12368         numptr_m1->val = rez;
12369         /* protect geting var value, is number now */
12370         numptr_m1->var = NULL;
12371         return 0;
12372  err:
12373         return -1;
12374 }
12375
12376 /* longest must be first */
12377 static const char op_tokens[] ALIGN1 = {
12378         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12379         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12380         '<','<',    0, TOK_LSHIFT,
12381         '>','>',    0, TOK_RSHIFT,
12382         '|','|',    0, TOK_OR,
12383         '&','&',    0, TOK_AND,
12384         '!','=',    0, TOK_NE,
12385         '<','=',    0, TOK_LE,
12386         '>','=',    0, TOK_GE,
12387         '=','=',    0, TOK_EQ,
12388         '|','=',    0, TOK_OR_ASSIGN,
12389         '&','=',    0, TOK_AND_ASSIGN,
12390         '*','=',    0, TOK_MUL_ASSIGN,
12391         '/','=',    0, TOK_DIV_ASSIGN,
12392         '%','=',    0, TOK_REM_ASSIGN,
12393         '+','=',    0, TOK_PLUS_ASSIGN,
12394         '-','=',    0, TOK_MINUS_ASSIGN,
12395         '-','-',    0, TOK_POST_DEC,
12396         '^','=',    0, TOK_XOR_ASSIGN,
12397         '+','+',    0, TOK_POST_INC,
12398         '*','*',    0, TOK_EXPONENT,
12399         '!',        0, TOK_NOT,
12400         '<',        0, TOK_LT,
12401         '>',        0, TOK_GT,
12402         '=',        0, TOK_ASSIGN,
12403         '|',        0, TOK_BOR,
12404         '&',        0, TOK_BAND,
12405         '*',        0, TOK_MUL,
12406         '/',        0, TOK_DIV,
12407         '%',        0, TOK_REM,
12408         '+',        0, TOK_ADD,
12409         '-',        0, TOK_SUB,
12410         '^',        0, TOK_BXOR,
12411         /* uniq */
12412         '~',        0, TOK_BNOT,
12413         ',',        0, TOK_COMMA,
12414         '?',        0, TOK_CONDITIONAL,
12415         ':',        0, TOK_CONDITIONAL_SEP,
12416         ')',        0, TOK_RPAREN,
12417         '(',        0, TOK_LPAREN,
12418         0
12419 };
12420 /* ptr to ")" */
12421 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12422
12423 static arith_t
12424 arith(const char *expr, int *perrcode)
12425 {
12426         char arithval; /* Current character under analysis */
12427         operator lasttok, op;
12428         operator prec;
12429
12430         const char *p = endexpression;
12431         int errcode;
12432
12433         size_t datasizes = strlen(expr) + 2;
12434
12435         /* Stack of integers */
12436         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12437          * in any given correct or incorrect expression is left as an exercise to
12438          * the reader. */
12439         v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12440                                 *numstackptr = numstack;
12441         /* Stack of operator tokens */
12442         operator *stack = alloca((datasizes) * sizeof(operator)),
12443                                 *stackptr = stack;
12444
12445         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
12446         *perrcode = errcode = 0;
12447
12448         while (1) {
12449                 arithval = *expr;
12450                 if (arithval == 0) {
12451                         if (p == endexpression) {
12452                                 /* Null expression. */
12453                                 return 0;
12454                         }
12455
12456                         /* This is only reached after all tokens have been extracted from the
12457                          * input stream. If there are still tokens on the operator stack, they
12458                          * are to be applied in order. At the end, there should be a final
12459                          * result on the integer stack */
12460
12461                         if (expr != endexpression + 1) {
12462                                 /* If we haven't done so already, */
12463                                 /* append a closing right paren */
12464                                 expr = endexpression;
12465                                 /* and let the loop process it. */
12466                                 continue;
12467                         }
12468                         /* At this point, we're done with the expression. */
12469                         if (numstackptr != numstack+1) {
12470                                 /* ... but if there isn't, it's bad */
12471  err:
12472                                 return (*perrcode = -1);
12473                         }
12474                         if (numstack->var) {
12475                                 /* expression is $((var)) only, lookup now */
12476                                 errcode = arith_lookup_val(numstack);
12477                         }
12478  ret:
12479                         *perrcode = errcode;
12480                         return numstack->val;
12481                 }
12482
12483                 /* Continue processing the expression. */
12484                 if (arith_isspace(arithval)) {
12485                         /* Skip whitespace */
12486                         goto prologue;
12487                 }
12488                 p = endofname(expr);
12489                 if (p != expr) {
12490                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
12491
12492                         numstackptr->var = alloca(var_name_size);
12493                         safe_strncpy(numstackptr->var, expr, var_name_size);
12494                         expr = p;
12495  num:
12496                         numstackptr->contidional_second_val_initialized = 0;
12497                         numstackptr++;
12498                         lasttok = TOK_NUM;
12499                         continue;
12500                 }
12501                 if (isdigit(arithval)) {
12502                         numstackptr->var = NULL;
12503 #if ENABLE_ASH_MATH_SUPPORT_64
12504                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
12505 #else
12506                         numstackptr->val = strtol(expr, (char **) &expr, 0);
12507 #endif
12508                         goto num;
12509                 }
12510                 for (p = op_tokens; ; p++) {
12511                         const char *o;
12512
12513                         if (*p == 0) {
12514                                 /* strange operator not found */
12515                                 goto err;
12516                         }
12517                         for (o = expr; *p && *o == *p; p++)
12518                                 o++;
12519                         if (! *p) {
12520                                 /* found */
12521                                 expr = o - 1;
12522                                 break;
12523                         }
12524                         /* skip tail uncompared token */
12525                         while (*p)
12526                                 p++;
12527                         /* skip zero delim */
12528                         p++;
12529                 }
12530                 op = p[1];
12531
12532                 /* post grammar: a++ reduce to num */
12533                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12534                         lasttok = TOK_NUM;
12535
12536                 /* Plus and minus are binary (not unary) _only_ if the last
12537                  * token was as number, or a right paren (which pretends to be
12538                  * a number, since it evaluates to one). Think about it.
12539                  * It makes sense. */
12540                 if (lasttok != TOK_NUM) {
12541                         switch (op) {
12542                         case TOK_ADD:
12543                                 op = TOK_UPLUS;
12544                                 break;
12545                         case TOK_SUB:
12546                                 op = TOK_UMINUS;
12547                                 break;
12548                         case TOK_POST_INC:
12549                                 op = TOK_PRE_INC;
12550                                 break;
12551                         case TOK_POST_DEC:
12552                                 op = TOK_PRE_DEC;
12553                                 break;
12554                         }
12555                 }
12556                 /* We don't want a unary operator to cause recursive descent on the
12557                  * stack, because there can be many in a row and it could cause an
12558                  * operator to be evaluated before its argument is pushed onto the
12559                  * integer stack. */
12560                 /* But for binary operators, "apply" everything on the operator
12561                  * stack until we find an operator with a lesser priority than the
12562                  * one we have just extracted. */
12563                 /* Left paren is given the lowest priority so it will never be
12564                  * "applied" in this way.
12565                  * if associativity is right and priority eq, applied also skip
12566                  */
12567                 prec = PREC(op);
12568                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12569                         /* not left paren or unary */
12570                         if (lasttok != TOK_NUM) {
12571                                 /* binary op must be preceded by a num */
12572                                 goto err;
12573                         }
12574                         while (stackptr != stack) {
12575                                 if (op == TOK_RPAREN) {
12576                                         /* The algorithm employed here is simple: while we don't
12577                                          * hit an open paren nor the bottom of the stack, pop
12578                                          * tokens and apply them */
12579                                         if (stackptr[-1] == TOK_LPAREN) {
12580                                                 --stackptr;
12581                                                 /* Any operator directly after a */
12582                                                 lasttok = TOK_NUM;
12583                                                 /* close paren should consider itself binary */
12584                                                 goto prologue;
12585                                         }
12586                                 } else {
12587                                         operator prev_prec = PREC(stackptr[-1]);
12588
12589                                         convert_prec_is_assing(prec);
12590                                         convert_prec_is_assing(prev_prec);
12591                                         if (prev_prec < prec)
12592                                                 break;
12593                                         /* check right assoc */
12594                                         if (prev_prec == prec && is_right_associativity(prec))
12595                                                 break;
12596                                 }
12597                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12598                                 if (errcode) goto ret;
12599                         }
12600                         if (op == TOK_RPAREN) {
12601                                 goto err;
12602                         }
12603                 }
12604
12605                 /* Push this operator to the stack and remember it. */
12606                 *stackptr++ = lasttok = op;
12607  prologue:
12608                 ++expr;
12609         } /* while */
12610 }
12611 #endif /* ASH_MATH_SUPPORT */
12612
12613
12614 /* ============ main() and helpers */
12615
12616 /*
12617  * Called to exit the shell.
12618  */
12619 static void exitshell(void) ATTRIBUTE_NORETURN;
12620 static void
12621 exitshell(void)
12622 {
12623         struct jmploc loc;
12624         char *p;
12625         int status;
12626
12627         status = exitstatus;
12628         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12629         if (setjmp(loc.loc)) {
12630                 if (exception == EXEXIT)
12631 /* dash bug: it just does _exit(exitstatus) here
12632  * but we have to do setjobctl(0) first!
12633  * (bug is still not fixed in dash-0.5.3 - if you run dash
12634  * under Midnight Commander, on exit from dash MC is backgrounded) */
12635                         status = exitstatus;
12636                 goto out;
12637         }
12638         exception_handler = &loc;
12639         p = trap[0];
12640         if (p) {
12641                 trap[0] = NULL;
12642                 evalstring(p, 0);
12643         }
12644         flush_stdout_stderr();
12645  out:
12646         setjobctl(0);
12647         _exit(status);
12648         /* NOTREACHED */
12649 }
12650
12651 static void
12652 init(void)
12653 {
12654         /* from input.c: */
12655         basepf.nextc = basepf.buf = basebuf;
12656
12657         /* from trap.c: */
12658         signal(SIGCHLD, SIG_DFL);
12659
12660         /* from var.c: */
12661         {
12662                 char **envp;
12663                 char ppid[sizeof(int)*3 + 1];
12664                 const char *p;
12665                 struct stat st1, st2;
12666
12667                 initvar();
12668                 for (envp = environ; envp && *envp; envp++) {
12669                         if (strchr(*envp, '=')) {
12670                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12671                         }
12672                 }
12673
12674                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12675                 setvar("PPID", ppid, 0);
12676
12677                 p = lookupvar("PWD");
12678                 if (p)
12679                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12680                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12681                                 p = '\0';
12682                 setpwd(p, 0);
12683         }
12684 }
12685
12686 /*
12687  * Process the shell command line arguments.
12688  */
12689 static void
12690 procargs(int argc, char **argv)
12691 {
12692         int i;
12693         const char *xminusc;
12694         char **xargv;
12695
12696         xargv = argv;
12697         arg0 = xargv[0];
12698         if (argc > 0)
12699                 xargv++;
12700         for (i = 0; i < NOPTS; i++)
12701                 optlist[i] = 2;
12702         argptr = xargv;
12703         options(1);
12704         xargv = argptr;
12705         xminusc = minusc;
12706         if (*xargv == NULL) {
12707                 if (xminusc)
12708                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12709                 sflag = 1;
12710         }
12711         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12712                 iflag = 1;
12713         if (mflag == 2)
12714                 mflag = iflag;
12715         for (i = 0; i < NOPTS; i++)
12716                 if (optlist[i] == 2)
12717                         optlist[i] = 0;
12718 #if DEBUG == 2
12719         debug = 1;
12720 #endif
12721         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12722         if (xminusc) {
12723                 minusc = *xargv++;
12724                 if (*xargv)
12725                         goto setarg0;
12726         } else if (!sflag) {
12727                 setinputfile(*xargv, 0);
12728  setarg0:
12729                 arg0 = *xargv++;
12730                 commandname = arg0;
12731         }
12732
12733         shellparam.p = xargv;
12734 #if ENABLE_ASH_GETOPTS
12735         shellparam.optind = 1;
12736         shellparam.optoff = -1;
12737 #endif
12738         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12739         while (*xargv) {
12740                 shellparam.nparam++;
12741                 xargv++;
12742         }
12743         optschanged();
12744 }
12745
12746 /*
12747  * Read /etc/profile or .profile.
12748  */
12749 static void
12750 read_profile(const char *name)
12751 {
12752         int skip;
12753
12754         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12755                 return;
12756         skip = cmdloop(0);
12757         popfile();
12758         if (skip)
12759                 exitshell();
12760 }
12761
12762 /*
12763  * This routine is called when an error or an interrupt occurs in an
12764  * interactive shell and control is returned to the main command loop.
12765  */
12766 static void
12767 reset(void)
12768 {
12769         /* from eval.c: */
12770         evalskip = 0;
12771         loopnest = 0;
12772         /* from input.c: */
12773         parselleft = parsenleft = 0;      /* clear input buffer */
12774         popallfiles();
12775         /* from parser.c: */
12776         tokpushback = 0;
12777         checkkwd = 0;
12778         /* from redir.c: */
12779         clearredir(0);
12780 }
12781
12782 #if PROFILE
12783 static short profile_buf[16384];
12784 extern int etext();
12785 #endif
12786
12787 /*
12788  * Main routine.  We initialize things, parse the arguments, execute
12789  * profiles if we're a login shell, and then call cmdloop to execute
12790  * commands.  The setjmp call sets up the location to jump to when an
12791  * exception occurs.  When an exception occurs the variable "state"
12792  * is used to figure out how far we had gotten.
12793  */
12794 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
12795 int ash_main(int argc, char **argv)
12796 {
12797         char *shinit;
12798         volatile int state;
12799         struct jmploc jmploc;
12800         struct stackmark smark;
12801
12802 #if PROFILE
12803         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12804 #endif
12805
12806 #if ENABLE_FEATURE_EDITING
12807         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12808 #endif
12809         state = 0;
12810         if (setjmp(jmploc.loc)) {
12811                 int e;
12812                 int s;
12813
12814                 reset();
12815
12816                 e = exception;
12817                 if (e == EXERROR)
12818                         exitstatus = 2;
12819                 s = state;
12820                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12821                         exitshell();
12822
12823                 if (e == EXINT) {
12824                         outcslow('\n', stderr);
12825                 }
12826                 popstackmark(&smark);
12827                 FORCE_INT_ON; /* enable interrupts */
12828                 if (s == 1)
12829                         goto state1;
12830                 if (s == 2)
12831                         goto state2;
12832                 if (s == 3)
12833                         goto state3;
12834                 goto state4;
12835         }
12836         exception_handler = &jmploc;
12837 #if DEBUG
12838         opentrace();
12839         trace_puts("Shell args: ");
12840         trace_puts_args(argv);
12841 #endif
12842         rootpid = getpid();
12843
12844 #if ENABLE_ASH_RANDOM_SUPPORT
12845         rseed = rootpid + time(NULL);
12846 #endif
12847         init();
12848         setstackmark(&smark);
12849         procargs(argc, argv);
12850 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12851         if (iflag) {
12852                 const char *hp = lookupvar("HISTFILE");
12853
12854                 if (hp == NULL) {
12855                         hp = lookupvar("HOME");
12856                         if (hp != NULL) {
12857                                 char *defhp = concat_path_file(hp, ".ash_history");
12858                                 setvar("HISTFILE", defhp, 0);
12859                                 free(defhp);
12860                         }
12861                 }
12862         }
12863 #endif
12864         if (argv[0] && argv[0][0] == '-')
12865                 isloginsh = 1;
12866         if (isloginsh) {
12867                 state = 1;
12868                 read_profile("/etc/profile");
12869  state1:
12870                 state = 2;
12871                 read_profile(".profile");
12872         }
12873  state2:
12874         state = 3;
12875         if (
12876 #ifndef linux
12877          getuid() == geteuid() && getgid() == getegid() &&
12878 #endif
12879          iflag
12880         ) {
12881                 shinit = lookupvar("ENV");
12882                 if (shinit != NULL && *shinit != '\0') {
12883                         read_profile(shinit);
12884                 }
12885         }
12886  state3:
12887         state = 4;
12888         if (minusc)
12889                 evalstring(minusc, 0);
12890
12891         if (sflag || minusc == NULL) {
12892 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12893                 if ( iflag ) {
12894                         const char *hp = lookupvar("HISTFILE");
12895
12896                         if (hp != NULL)
12897                                 line_input_state->hist_file = hp;
12898                 }
12899 #endif
12900  state4: /* XXX ??? - why isn't this before the "if" statement */
12901                 cmdloop(1);
12902         }
12903 #if PROFILE
12904         monitor(0);
12905 #endif
12906 #ifdef GPROF
12907         {
12908                 extern void _mcleanup(void);
12909                 _mcleanup();
12910         }
12911 #endif
12912         exitshell();
12913         /* NOTREACHED */
12914 }
12915
12916 #if DEBUG
12917 const char *applet_name = "debug stuff usage";
12918 int main(int argc, char **argv)
12919 {
12920         return ash_main(argc, argv);
12921 }
12922 #endif
12923
12924
12925 /*-
12926  * Copyright (c) 1989, 1991, 1993, 1994
12927  *      The Regents of the University of California.  All rights reserved.
12928  *
12929  * This code is derived from software contributed to Berkeley by
12930  * Kenneth Almquist.
12931  *
12932  * Redistribution and use in source and binary forms, with or without
12933  * modification, are permitted provided that the following conditions
12934  * are met:
12935  * 1. Redistributions of source code must retain the above copyright
12936  *    notice, this list of conditions and the following disclaimer.
12937  * 2. Redistributions in binary form must reproduce the above copyright
12938  *    notice, this list of conditions and the following disclaimer in the
12939  *    documentation and/or other materials provided with the distribution.
12940  * 3. Neither the name of the University nor the names of its contributors
12941  *    may be used to endorse or promote products derived from this software
12942  *    without specific prior written permission.
12943  *
12944  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12945  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12946  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12947  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12948  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12949  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12950  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12951  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12952  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12953  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12954  * SUCH DAMAGE.
12955  */