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