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