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