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