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