61217204357938994cdc88ff701b61c22a8a10bb
[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 static int
9080 minus_o(char *name, int val)
9081 {
9082         int i;
9083
9084         if (name) {
9085                 for (i = 0; i < NOPTS; i++) {
9086                         if (strcmp(name, optnames(i)) == 0) {
9087                                 optlist[i] = val;
9088                                 return 0;
9089                         }
9090                 }
9091                 ash_msg("illegal option -o %s", name);
9092                 return 1;
9093         }
9094         out1str("Current option settings\n");
9095         for (i = 0; i < NOPTS; i++)
9096                 out1fmt("%-16s%s\n", optnames(i),
9097                                 optlist[i] ? "on" : "off");
9098         return 0;
9099 }
9100 static void
9101 setoption(int flag, int val)
9102 {
9103         int i;
9104
9105         for (i = 0; i < NOPTS; i++) {
9106                 if (optletters(i) == flag) {
9107                         optlist[i] = val;
9108                         return;
9109                 }
9110         }
9111         ash_msg_and_raise_error("illegal option -%c", flag);
9112         /* NOTREACHED */
9113 }
9114 static int
9115 options(int cmdline)
9116 {
9117         char *p;
9118         int val;
9119         int c;
9120
9121         if (cmdline)
9122                 minusc = NULL;
9123         while ((p = *argptr) != NULL) {
9124                 c = *p++;
9125                 if (c != '-' && c != '+')
9126                         break;
9127                 argptr++;
9128                 val = 0; /* val = 0 if c == '+' */
9129                 if (c == '-') {
9130                         val = 1;
9131                         if (p[0] == '\0' || LONE_DASH(p)) {
9132                                 if (!cmdline) {
9133                                         /* "-" means turn off -x and -v */
9134                                         if (p[0] == '\0')
9135                                                 xflag = vflag = 0;
9136                                         /* "--" means reset params */
9137                                         else if (*argptr == NULL)
9138                                                 setparam(argptr);
9139                                 }
9140                                 break;    /* "-" or  "--" terminates options */
9141                         }
9142                 }
9143                 /* first char was + or - */
9144                 while ((c = *p++) != '\0') {
9145                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9146                         if (c == 'c' && cmdline) {
9147                                 minusc = p;     /* command is after shell args */
9148                         } else if (c == 'o') {
9149                                 if (minus_o(*argptr, val)) {
9150                                         /* it already printed err message */
9151                                         return 1; /* error */
9152                                 }
9153                                 if (*argptr)
9154                                         argptr++;
9155                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9156                                 isloginsh = 1;
9157                         /* bash does not accept +-login, we also won't */
9158                         } else if (cmdline && val && (c == '-')) { /* long options */
9159                                 if (strcmp(p, "login") == 0)
9160                                         isloginsh = 1;
9161                                 break;
9162                         } else {
9163                                 setoption(c, val);
9164                         }
9165                 }
9166         }
9167         return 0;
9168 }
9169
9170 /*
9171  * The shift builtin command.
9172  */
9173 static int
9174 shiftcmd(int argc, char **argv)
9175 {
9176         int n;
9177         char **ap1, **ap2;
9178
9179         n = 1;
9180         if (argc > 1)
9181                 n = number(argv[1]);
9182         if (n > shellparam.nparam)
9183                 ash_msg_and_raise_error("can't shift that many");
9184         INT_OFF;
9185         shellparam.nparam -= n;
9186         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9187                 if (shellparam.malloced)
9188                         free(*ap1);
9189         }
9190         ap2 = shellparam.p;
9191         while ((*ap2++ = *ap1++) != NULL);
9192 #if ENABLE_ASH_GETOPTS
9193         shellparam.optind = 1;
9194         shellparam.optoff = -1;
9195 #endif
9196         INT_ON;
9197         return 0;
9198 }
9199
9200 /*
9201  * POSIX requires that 'set' (but not export or readonly) output the
9202  * variables in lexicographic order - by the locale's collating order (sigh).
9203  * Maybe we could keep them in an ordered balanced binary tree
9204  * instead of hashed lists.
9205  * For now just roll 'em through qsort for printing...
9206  */
9207 static int
9208 showvars(const char *sep_prefix, int on, int off)
9209 {
9210         const char *sep;
9211         char **ep, **epend;
9212
9213         ep = listvars(on, off, &epend);
9214         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9215
9216         sep = *sep_prefix ? " " : sep_prefix;
9217
9218         for (; ep < epend; ep++) {
9219                 const char *p;
9220                 const char *q;
9221
9222                 p = strchrnul(*ep, '=');
9223                 q = nullstr;
9224                 if (*p)
9225                         q = single_quote(++p);
9226                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9227         }
9228         return 0;
9229 }
9230
9231 /*
9232  * The set command builtin.
9233  */
9234 static int
9235 setcmd(int argc, char **argv)
9236 {
9237         int retval;
9238
9239         if (argc == 1)
9240                 return showvars(nullstr, 0, VUNSET);
9241         INT_OFF;
9242         retval = 1;
9243         if (!options(0)) { /* if no parse error... */
9244                 retval = 0;
9245                 optschanged();
9246                 if (*argptr != NULL) {
9247                         setparam(argptr);
9248                 }
9249         }
9250         INT_ON;
9251         return retval;
9252 }
9253
9254 #if ENABLE_ASH_RANDOM_SUPPORT
9255 /* Roughly copied from bash.. */
9256 static void
9257 change_random(const char *value)
9258 {
9259         if (value == NULL) {
9260                 /* "get", generate */
9261                 char buf[16];
9262
9263                 rseed = rseed * 1103515245 + 12345;
9264                 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9265                 /* set without recursion */
9266                 setvar(vrandom.text, buf, VNOFUNC);
9267                 vrandom.flags &= ~VNOFUNC;
9268         } else {
9269                 /* set/reset */
9270                 rseed = strtoul(value, (char **)NULL, 10);
9271         }
9272 }
9273 #endif
9274
9275 #if ENABLE_ASH_GETOPTS
9276 static int
9277 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9278 {
9279         char *p, *q;
9280         char c = '?';
9281         int done = 0;
9282         int err = 0;
9283         char s[12];
9284         char **optnext;
9285
9286         if (*param_optind < 1)
9287                 return 1;
9288         optnext = optfirst + *param_optind - 1;
9289
9290         if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9291                 p = NULL;
9292         else
9293                 p = optnext[-1] + *optoff;
9294         if (p == NULL || *p == '\0') {
9295                 /* Current word is done, advance */
9296                 p = *optnext;
9297                 if (p == NULL || *p != '-' || *++p == '\0') {
9298  atend:
9299                         p = NULL;
9300                         done = 1;
9301                         goto out;
9302                 }
9303                 optnext++;
9304                 if (LONE_DASH(p))        /* check for "--" */
9305                         goto atend;
9306         }
9307
9308         c = *p++;
9309         for (q = optstr; *q != c; ) {
9310                 if (*q == '\0') {
9311                         if (optstr[0] == ':') {
9312                                 s[0] = c;
9313                                 s[1] = '\0';
9314                                 err |= setvarsafe("OPTARG", s, 0);
9315                         } else {
9316                                 fprintf(stderr, "Illegal option -%c\n", c);
9317                                 unsetvar("OPTARG");
9318                         }
9319                         c = '?';
9320                         goto out;
9321                 }
9322                 if (*++q == ':')
9323                         q++;
9324         }
9325
9326         if (*++q == ':') {
9327                 if (*p == '\0' && (p = *optnext) == NULL) {
9328                         if (optstr[0] == ':') {
9329                                 s[0] = c;
9330                                 s[1] = '\0';
9331                                 err |= setvarsafe("OPTARG", s, 0);
9332                                 c = ':';
9333                         } else {
9334                                 fprintf(stderr, "No arg for -%c option\n", c);
9335                                 unsetvar("OPTARG");
9336                                 c = '?';
9337                         }
9338                         goto out;
9339                 }
9340
9341                 if (p == *optnext)
9342                         optnext++;
9343                 err |= setvarsafe("OPTARG", p, 0);
9344                 p = NULL;
9345         } else
9346                 err |= setvarsafe("OPTARG", nullstr, 0);
9347  out:
9348         *optoff = p ? p - *(optnext - 1) : -1;
9349         *param_optind = optnext - optfirst + 1;
9350         fmtstr(s, sizeof(s), "%d", *param_optind);
9351         err |= setvarsafe("OPTIND", s, VNOFUNC);
9352         s[0] = c;
9353         s[1] = '\0';
9354         err |= setvarsafe(optvar, s, 0);
9355         if (err) {
9356                 *param_optind = 1;
9357                 *optoff = -1;
9358                 flush_stdout_stderr();
9359                 raise_exception(EXERROR);
9360         }
9361         return done;
9362 }
9363
9364 /*
9365  * The getopts builtin.  Shellparam.optnext points to the next argument
9366  * to be processed.  Shellparam.optptr points to the next character to
9367  * be processed in the current argument.  If shellparam.optnext is NULL,
9368  * then it's the first time getopts has been called.
9369  */
9370 static int
9371 getoptscmd(int argc, char **argv)
9372 {
9373         char **optbase;
9374
9375         if (argc < 3)
9376                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9377         if (argc == 3) {
9378                 optbase = shellparam.p;
9379                 if (shellparam.optind > shellparam.nparam + 1) {
9380                         shellparam.optind = 1;
9381                         shellparam.optoff = -1;
9382                 }
9383         } else {
9384                 optbase = &argv[3];
9385                 if (shellparam.optind > argc - 2) {
9386                         shellparam.optind = 1;
9387                         shellparam.optoff = -1;
9388                 }
9389         }
9390
9391         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9392                         &shellparam.optoff);
9393 }
9394 #endif /* ASH_GETOPTS */
9395
9396
9397 /* ============ Shell parser */
9398
9399 /*
9400  * NEOF is returned by parsecmd when it encounters an end of file.  It
9401  * must be distinct from NULL, so we use the address of a variable that
9402  * happens to be handy.
9403  */
9404 static smallint tokpushback;           /* last token pushed back */
9405 #define NEOF ((union node *)&tokpushback)
9406 static smallint parsebackquote;        /* nonzero if we are inside backquotes */
9407 static int lasttoken;                  /* last token read */
9408 static char *wordtext;                 /* text of last word returned by readtoken */
9409 static struct nodelist *backquotelist;
9410 static union node *redirnode;
9411 static struct heredoc *heredoc;
9412 static smallint quoteflag;             /* set if (part of) last token was quoted */
9413
9414 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9415 static void
9416 raise_error_syntax(const char *msg)
9417 {
9418         ash_msg_and_raise_error("syntax error: %s", msg);
9419         /* NOTREACHED */
9420 }
9421
9422 /*
9423  * Called when an unexpected token is read during the parse.  The argument
9424  * is the token that is expected, or -1 if more than one type of token can
9425  * occur at this point.
9426  */
9427 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9428 static void
9429 raise_error_unexpected_syntax(int token)
9430 {
9431         char msg[64];
9432         int l;
9433
9434         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9435         if (token >= 0)
9436                 sprintf(msg + l, " (expecting %s)", tokname(token));
9437         raise_error_syntax(msg);
9438         /* NOTREACHED */
9439 }
9440
9441 #define EOFMARKLEN 79
9442
9443 struct heredoc {
9444         struct heredoc *next;   /* next here document in list */
9445         union node *here;               /* redirection node */
9446         char *eofmark;          /* string indicating end of input */
9447         int striptabs;          /* if set, strip leading tabs */
9448 };
9449
9450 static struct heredoc *heredoclist;    /* list of here documents to read */
9451
9452 /* parsing is heavily cross-recursive, need these forward decls */
9453 static union node *andor(void);
9454 static union node *pipeline(void);
9455 static union node *parse_command(void);
9456 static void parseheredoc(void);
9457 static char peektoken(void);
9458 static int readtoken(void);
9459
9460 static union node *
9461 list(int nlflag)
9462 {
9463         union node *n1, *n2, *n3;
9464         int tok;
9465
9466         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9467         if (nlflag == 2 && peektoken())
9468                 return NULL;
9469         n1 = NULL;
9470         for (;;) {
9471                 n2 = andor();
9472                 tok = readtoken();
9473                 if (tok == TBACKGND) {
9474                         if (n2->type == NPIPE) {
9475                                 n2->npipe.backgnd = 1;
9476                         } else {
9477                                 if (n2->type != NREDIR) {
9478                                         n3 = stalloc(sizeof(struct nredir));
9479                                         n3->nredir.n = n2;
9480                                         n3->nredir.redirect = NULL;
9481                                         n2 = n3;
9482                                 }
9483                                 n2->type = NBACKGND;
9484                         }
9485                 }
9486                 if (n1 == NULL) {
9487                         n1 = n2;
9488                 } else {
9489                         n3 = stalloc(sizeof(struct nbinary));
9490                         n3->type = NSEMI;
9491                         n3->nbinary.ch1 = n1;
9492                         n3->nbinary.ch2 = n2;
9493                         n1 = n3;
9494                 }
9495                 switch (tok) {
9496                 case TBACKGND:
9497                 case TSEMI:
9498                         tok = readtoken();
9499                         /* fall through */
9500                 case TNL:
9501                         if (tok == TNL) {
9502                                 parseheredoc();
9503                                 if (nlflag == 1)
9504                                         return n1;
9505                         } else {
9506                                 tokpushback = 1;
9507                         }
9508                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9509                         if (peektoken())
9510                                 return n1;
9511                         break;
9512                 case TEOF:
9513                         if (heredoclist)
9514                                 parseheredoc();
9515                         else
9516                                 pungetc();              /* push back EOF on input */
9517                         return n1;
9518                 default:
9519                         if (nlflag == 1)
9520                                 raise_error_unexpected_syntax(-1);
9521                         tokpushback = 1;
9522                         return n1;
9523                 }
9524         }
9525 }
9526
9527 static union node *
9528 andor(void)
9529 {
9530         union node *n1, *n2, *n3;
9531         int t;
9532
9533         n1 = pipeline();
9534         for (;;) {
9535                 t = readtoken();
9536                 if (t == TAND) {
9537                         t = NAND;
9538                 } else if (t == TOR) {
9539                         t = NOR;
9540                 } else {
9541                         tokpushback = 1;
9542                         return n1;
9543                 }
9544                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9545                 n2 = pipeline();
9546                 n3 = stalloc(sizeof(struct nbinary));
9547                 n3->type = t;
9548                 n3->nbinary.ch1 = n1;
9549                 n3->nbinary.ch2 = n2;
9550                 n1 = n3;
9551         }
9552 }
9553
9554 static union node *
9555 pipeline(void)
9556 {
9557         union node *n1, *n2, *pipenode;
9558         struct nodelist *lp, *prev;
9559         int negate;
9560
9561         negate = 0;
9562         TRACE(("pipeline: entered\n"));
9563         if (readtoken() == TNOT) {
9564                 negate = !negate;
9565                 checkkwd = CHKKWD | CHKALIAS;
9566         } else
9567                 tokpushback = 1;
9568         n1 = parse_command();
9569         if (readtoken() == TPIPE) {
9570                 pipenode = stalloc(sizeof(struct npipe));
9571                 pipenode->type = NPIPE;
9572                 pipenode->npipe.backgnd = 0;
9573                 lp = stalloc(sizeof(struct nodelist));
9574                 pipenode->npipe.cmdlist = lp;
9575                 lp->n = n1;
9576                 do {
9577                         prev = lp;
9578                         lp = stalloc(sizeof(struct nodelist));
9579                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9580                         lp->n = parse_command();
9581                         prev->next = lp;
9582                 } while (readtoken() == TPIPE);
9583                 lp->next = NULL;
9584                 n1 = pipenode;
9585         }
9586         tokpushback = 1;
9587         if (negate) {
9588                 n2 = stalloc(sizeof(struct nnot));
9589                 n2->type = NNOT;
9590                 n2->nnot.com = n1;
9591                 return n2;
9592         }
9593         return n1;
9594 }
9595
9596 static union node *
9597 makename(void)
9598 {
9599         union node *n;
9600
9601         n = stalloc(sizeof(struct narg));
9602         n->type = NARG;
9603         n->narg.next = NULL;
9604         n->narg.text = wordtext;
9605         n->narg.backquote = backquotelist;
9606         return n;
9607 }
9608
9609 static void
9610 fixredir(union node *n, const char *text, int err)
9611 {
9612         TRACE(("Fix redir %s %d\n", text, err));
9613         if (!err)
9614                 n->ndup.vname = NULL;
9615
9616         if (isdigit(text[0]) && text[1] == '\0')
9617                 n->ndup.dupfd = text[0] - '0';
9618         else if (LONE_DASH(text))
9619                 n->ndup.dupfd = -1;
9620         else {
9621                 if (err)
9622                         raise_error_syntax("Bad fd number");
9623                 n->ndup.vname = makename();
9624         }
9625 }
9626
9627 /*
9628  * Returns true if the text contains nothing to expand (no dollar signs
9629  * or backquotes).
9630  */
9631 static int
9632 noexpand(char *text)
9633 {
9634         char *p;
9635         char c;
9636
9637         p = text;
9638         while ((c = *p++) != '\0') {
9639                 if (c == CTLQUOTEMARK)
9640                         continue;
9641                 if (c == CTLESC)
9642                         p++;
9643                 else if (SIT(c, BASESYNTAX) == CCTL)
9644                         return 0;
9645         }
9646         return 1;
9647 }
9648
9649 static void
9650 parsefname(void)
9651 {
9652         union node *n = redirnode;
9653
9654         if (readtoken() != TWORD)
9655                 raise_error_unexpected_syntax(-1);
9656         if (n->type == NHERE) {
9657                 struct heredoc *here = heredoc;
9658                 struct heredoc *p;
9659                 int i;
9660
9661                 if (quoteflag == 0)
9662                         n->type = NXHERE;
9663                 TRACE(("Here document %d\n", n->type));
9664                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9665                         raise_error_syntax("Illegal eof marker for << redirection");
9666                 rmescapes(wordtext);
9667                 here->eofmark = wordtext;
9668                 here->next = NULL;
9669                 if (heredoclist == NULL)
9670                         heredoclist = here;
9671                 else {
9672                         for (p = heredoclist; p->next; p = p->next);
9673                         p->next = here;
9674                 }
9675         } else if (n->type == NTOFD || n->type == NFROMFD) {
9676                 fixredir(n, wordtext, 0);
9677         } else {
9678                 n->nfile.fname = makename();
9679         }
9680 }
9681
9682 static union node *
9683 simplecmd(void)
9684 {
9685         union node *args, **app;
9686         union node *n = NULL;
9687         union node *vars, **vpp;
9688         union node **rpp, *redir;
9689         int savecheckkwd;
9690
9691         args = NULL;
9692         app = &args;
9693         vars = NULL;
9694         vpp = &vars;
9695         redir = NULL;
9696         rpp = &redir;
9697
9698         savecheckkwd = CHKALIAS;
9699         for (;;) {
9700                 checkkwd = savecheckkwd;
9701                 switch (readtoken()) {
9702                 case TWORD:
9703                         n = stalloc(sizeof(struct narg));
9704                         n->type = NARG;
9705                         n->narg.text = wordtext;
9706                         n->narg.backquote = backquotelist;
9707                         if (savecheckkwd && isassignment(wordtext)) {
9708                                 *vpp = n;
9709                                 vpp = &n->narg.next;
9710                         } else {
9711                                 *app = n;
9712                                 app = &n->narg.next;
9713                                 savecheckkwd = 0;
9714                         }
9715                         break;
9716                 case TREDIR:
9717                         *rpp = n = redirnode;
9718                         rpp = &n->nfile.next;
9719                         parsefname();   /* read name of redirection file */
9720                         break;
9721                 case TLP:
9722                         if (args && app == &args->narg.next
9723                          && !vars && !redir
9724                         ) {
9725                                 struct builtincmd *bcmd;
9726                                 const char *name;
9727
9728                                 /* We have a function */
9729                                 if (readtoken() != TRP)
9730                                         raise_error_unexpected_syntax(TRP);
9731                                 name = n->narg.text;
9732                                 if (!goodname(name)
9733                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9734                                 ) {
9735                                         raise_error_syntax("Bad function name");
9736                                 }
9737                                 n->type = NDEFUN;
9738                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9739                                 n->narg.next = parse_command();
9740                                 return n;
9741                         }
9742                         /* fall through */
9743                 default:
9744                         tokpushback = 1;
9745                         goto out;
9746                 }
9747         }
9748  out:
9749         *app = NULL;
9750         *vpp = NULL;
9751         *rpp = NULL;
9752         n = stalloc(sizeof(struct ncmd));
9753         n->type = NCMD;
9754         n->ncmd.args = args;
9755         n->ncmd.assign = vars;
9756         n->ncmd.redirect = redir;
9757         return n;
9758 }
9759
9760 static union node *
9761 parse_command(void)
9762 {
9763         union node *n1, *n2;
9764         union node *ap, **app;
9765         union node *cp, **cpp;
9766         union node *redir, **rpp;
9767         union node **rpp2;
9768         int t;
9769
9770         redir = NULL;
9771         rpp2 = &redir;
9772
9773         switch (readtoken()) {
9774         default:
9775                 raise_error_unexpected_syntax(-1);
9776                 /* NOTREACHED */
9777         case TIF:
9778                 n1 = stalloc(sizeof(struct nif));
9779                 n1->type = NIF;
9780                 n1->nif.test = list(0);
9781                 if (readtoken() != TTHEN)
9782                         raise_error_unexpected_syntax(TTHEN);
9783                 n1->nif.ifpart = list(0);
9784                 n2 = n1;
9785                 while (readtoken() == TELIF) {
9786                         n2->nif.elsepart = stalloc(sizeof(struct nif));
9787                         n2 = n2->nif.elsepart;
9788                         n2->type = NIF;
9789                         n2->nif.test = list(0);
9790                         if (readtoken() != TTHEN)
9791                                 raise_error_unexpected_syntax(TTHEN);
9792                         n2->nif.ifpart = list(0);
9793                 }
9794                 if (lasttoken == TELSE)
9795                         n2->nif.elsepart = list(0);
9796                 else {
9797                         n2->nif.elsepart = NULL;
9798                         tokpushback = 1;
9799                 }
9800                 t = TFI;
9801                 break;
9802         case TWHILE:
9803         case TUNTIL: {
9804                 int got;
9805                 n1 = stalloc(sizeof(struct nbinary));
9806                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9807                 n1->nbinary.ch1 = list(0);
9808                 got = readtoken();
9809                 if (got != TDO) {
9810                         TRACE(("expecting DO got %s %s\n", tokname(got),
9811                                         got == TWORD ? wordtext : ""));
9812                         raise_error_unexpected_syntax(TDO);
9813                 }
9814                 n1->nbinary.ch2 = list(0);
9815                 t = TDONE;
9816                 break;
9817         }
9818         case TFOR:
9819                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9820                         raise_error_syntax("Bad for loop variable");
9821                 n1 = stalloc(sizeof(struct nfor));
9822                 n1->type = NFOR;
9823                 n1->nfor.var = wordtext;
9824                 checkkwd = CHKKWD | CHKALIAS;
9825                 if (readtoken() == TIN) {
9826                         app = &ap;
9827                         while (readtoken() == TWORD) {
9828                                 n2 = stalloc(sizeof(struct narg));
9829                                 n2->type = NARG;
9830                                 n2->narg.text = wordtext;
9831                                 n2->narg.backquote = backquotelist;
9832                                 *app = n2;
9833                                 app = &n2->narg.next;
9834                         }
9835                         *app = NULL;
9836                         n1->nfor.args = ap;
9837                         if (lasttoken != TNL && lasttoken != TSEMI)
9838                                 raise_error_unexpected_syntax(-1);
9839                 } else {
9840                         n2 = stalloc(sizeof(struct narg));
9841                         n2->type = NARG;
9842                         n2->narg.text = (char *)dolatstr;
9843                         n2->narg.backquote = NULL;
9844                         n2->narg.next = NULL;
9845                         n1->nfor.args = n2;
9846                         /*
9847                          * Newline or semicolon here is optional (but note
9848                          * that the original Bourne shell only allowed NL).
9849                          */
9850                         if (lasttoken != TNL && lasttoken != TSEMI)
9851                                 tokpushback = 1;
9852                 }
9853                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9854                 if (readtoken() != TDO)
9855                         raise_error_unexpected_syntax(TDO);
9856                 n1->nfor.body = list(0);
9857                 t = TDONE;
9858                 break;
9859         case TCASE:
9860                 n1 = stalloc(sizeof(struct ncase));
9861                 n1->type = NCASE;
9862                 if (readtoken() != TWORD)
9863                         raise_error_unexpected_syntax(TWORD);
9864                 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9865                 n2->type = NARG;
9866                 n2->narg.text = wordtext;
9867                 n2->narg.backquote = backquotelist;
9868                 n2->narg.next = NULL;
9869                 do {
9870                         checkkwd = CHKKWD | CHKALIAS;
9871                 } while (readtoken() == TNL);
9872                 if (lasttoken != TIN)
9873                         raise_error_unexpected_syntax(TIN);
9874                 cpp = &n1->ncase.cases;
9875  next_case:
9876                 checkkwd = CHKNL | CHKKWD;
9877                 t = readtoken();
9878                 while (t != TESAC) {
9879                         if (lasttoken == TLP)
9880                                 readtoken();
9881                         *cpp = cp = stalloc(sizeof(struct nclist));
9882                         cp->type = NCLIST;
9883                         app = &cp->nclist.pattern;
9884                         for (;;) {
9885                                 *app = ap = stalloc(sizeof(struct narg));
9886                                 ap->type = NARG;
9887                                 ap->narg.text = wordtext;
9888                                 ap->narg.backquote = backquotelist;
9889                                 if (readtoken() != TPIPE)
9890                                         break;
9891                                 app = &ap->narg.next;
9892                                 readtoken();
9893                         }
9894                         ap->narg.next = NULL;
9895                         if (lasttoken != TRP)
9896                                 raise_error_unexpected_syntax(TRP);
9897                         cp->nclist.body = list(2);
9898
9899                         cpp = &cp->nclist.next;
9900
9901                         checkkwd = CHKNL | CHKKWD;
9902                         t = readtoken();
9903                         if (t != TESAC) {
9904                                 if (t != TENDCASE)
9905                                         raise_error_unexpected_syntax(TENDCASE);
9906                                 goto next_case;
9907                         }
9908                 }
9909                 *cpp = NULL;
9910                 goto redir;
9911         case TLP:
9912                 n1 = stalloc(sizeof(struct nredir));
9913                 n1->type = NSUBSHELL;
9914                 n1->nredir.n = list(0);
9915                 n1->nredir.redirect = NULL;
9916                 t = TRP;
9917                 break;
9918         case TBEGIN:
9919                 n1 = list(0);
9920                 t = TEND;
9921                 break;
9922         case TWORD:
9923         case TREDIR:
9924                 tokpushback = 1;
9925                 return simplecmd();
9926         }
9927
9928         if (readtoken() != t)
9929                 raise_error_unexpected_syntax(t);
9930
9931  redir:
9932         /* Now check for redirection which may follow command */
9933         checkkwd = CHKKWD | CHKALIAS;
9934         rpp = rpp2;
9935         while (readtoken() == TREDIR) {
9936                 *rpp = n2 = redirnode;
9937                 rpp = &n2->nfile.next;
9938                 parsefname();
9939         }
9940         tokpushback = 1;
9941         *rpp = NULL;
9942         if (redir) {
9943                 if (n1->type != NSUBSHELL) {
9944                         n2 = stalloc(sizeof(struct nredir));
9945                         n2->type = NREDIR;
9946                         n2->nredir.n = n1;
9947                         n1 = n2;
9948                 }
9949                 n1->nredir.redirect = redir;
9950         }
9951         return n1;
9952 }
9953
9954 /*
9955  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
9956  * is not NULL, read a here document.  In the latter case, eofmark is the
9957  * word which marks the end of the document and striptabs is true if
9958  * leading tabs should be stripped from the document.  The argument firstc
9959  * is the first character of the input token or document.
9960  *
9961  * Because C does not have internal subroutines, I have simulated them
9962  * using goto's to implement the subroutine linkage.  The following macros
9963  * will run code that appears at the end of readtoken1.
9964  */
9965
9966 #define CHECKEND()      {goto checkend; checkend_return:;}
9967 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
9968 #define PARSESUB()      {goto parsesub; parsesub_return:;}
9969 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9970 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9971 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
9972
9973 static int
9974 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9975 {
9976         /* NB: syntax parameter fits into smallint */
9977         int c = firstc;
9978         char *out;
9979         int len;
9980         char line[EOFMARKLEN + 1];
9981         struct nodelist *bqlist;
9982         smallint quotef;
9983         smallint dblquote;
9984         smallint oldstyle;
9985         smallint prevsyntax; /* syntax before arithmetic */
9986 #if ENABLE_ASH_EXPAND_PRMT
9987         smallint pssyntax;   /* we are expanding a prompt string */
9988 #endif
9989         int varnest;         /* levels of variables expansion */
9990         int arinest;         /* levels of arithmetic expansion */
9991         int parenlevel;      /* levels of parens in arithmetic */
9992         int dqvarnest;       /* levels of variables expansion within double quotes */
9993
9994 #if __GNUC__
9995         /* Avoid longjmp clobbering */
9996         (void) &out;
9997         (void) &quotef;
9998         (void) &dblquote;
9999         (void) &varnest;
10000         (void) &arinest;
10001         (void) &parenlevel;
10002         (void) &dqvarnest;
10003         (void) &oldstyle;
10004         (void) &prevsyntax;
10005         (void) &syntax;
10006 #endif
10007         startlinno = plinno;
10008         bqlist = NULL;
10009         quotef = 0;
10010         oldstyle = 0;
10011         prevsyntax = 0;
10012 #if ENABLE_ASH_EXPAND_PRMT
10013         pssyntax = (syntax == PSSYNTAX);
10014         if (pssyntax)
10015                 syntax = DQSYNTAX;
10016 #endif
10017         dblquote = (syntax == DQSYNTAX);
10018         varnest = 0;
10019         arinest = 0;
10020         parenlevel = 0;
10021         dqvarnest = 0;
10022
10023         STARTSTACKSTR(out);
10024         loop: { /* for each line, until end of word */
10025                 CHECKEND();     /* set c to PEOF if at end of here document */
10026                 for (;;) {      /* until end of line or end of word */
10027                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10028                         switch (SIT(c, syntax)) {
10029                         case CNL:       /* '\n' */
10030                                 if (syntax == BASESYNTAX)
10031                                         goto endword;   /* exit outer loop */
10032                                 USTPUTC(c, out);
10033                                 plinno++;
10034                                 if (doprompt)
10035                                         setprompt(2);
10036                                 c = pgetc();
10037                                 goto loop;              /* continue outer loop */
10038                         case CWORD:
10039                                 USTPUTC(c, out);
10040                                 break;
10041                         case CCTL:
10042                                 if (eofmark == NULL || dblquote)
10043                                         USTPUTC(CTLESC, out);
10044                                 USTPUTC(c, out);
10045                                 break;
10046                         case CBACK:     /* backslash */
10047                                 c = pgetc2();
10048                                 if (c == PEOF) {
10049                                         USTPUTC(CTLESC, out);
10050                                         USTPUTC('\\', out);
10051                                         pungetc();
10052                                 } else if (c == '\n') {
10053                                         if (doprompt)
10054                                                 setprompt(2);
10055                                 } else {
10056 #if ENABLE_ASH_EXPAND_PRMT
10057                                         if (c == '$' && pssyntax) {
10058                                                 USTPUTC(CTLESC, out);
10059                                                 USTPUTC('\\', out);
10060                                         }
10061 #endif
10062                                         if (dblquote &&
10063                                                 c != '\\' && c != '`' &&
10064                                                 c != '$' && (
10065                                                         c != '"' ||
10066                                                         eofmark != NULL)
10067                                         ) {
10068                                                 USTPUTC(CTLESC, out);
10069                                                 USTPUTC('\\', out);
10070                                         }
10071                                         if (SIT(c, SQSYNTAX) == CCTL)
10072                                                 USTPUTC(CTLESC, out);
10073                                         USTPUTC(c, out);
10074                                         quotef = 1;
10075                                 }
10076                                 break;
10077                         case CSQUOTE:
10078                                 syntax = SQSYNTAX;
10079  quotemark:
10080                                 if (eofmark == NULL) {
10081                                         USTPUTC(CTLQUOTEMARK, out);
10082                                 }
10083                                 break;
10084                         case CDQUOTE:
10085                                 syntax = DQSYNTAX;
10086                                 dblquote = 1;
10087                                 goto quotemark;
10088                         case CENDQUOTE:
10089                                 if (eofmark != NULL && arinest == 0
10090                                  && varnest == 0
10091                                 ) {
10092                                         USTPUTC(c, out);
10093                                 } else {
10094                                         if (dqvarnest == 0) {
10095                                                 syntax = BASESYNTAX;
10096                                                 dblquote = 0;
10097                                         }
10098                                         quotef = 1;
10099                                         goto quotemark;
10100                                 }
10101                                 break;
10102                         case CVAR:      /* '$' */
10103                                 PARSESUB();             /* parse substitution */
10104                                 break;
10105                         case CENDVAR:   /* '}' */
10106                                 if (varnest > 0) {
10107                                         varnest--;
10108                                         if (dqvarnest > 0) {
10109                                                 dqvarnest--;
10110                                         }
10111                                         USTPUTC(CTLENDVAR, out);
10112                                 } else {
10113                                         USTPUTC(c, out);
10114                                 }
10115                                 break;
10116 #if ENABLE_ASH_MATH_SUPPORT
10117                         case CLP:       /* '(' in arithmetic */
10118                                 parenlevel++;
10119                                 USTPUTC(c, out);
10120                                 break;
10121                         case CRP:       /* ')' in arithmetic */
10122                                 if (parenlevel > 0) {
10123                                         USTPUTC(c, out);
10124                                         --parenlevel;
10125                                 } else {
10126                                         if (pgetc() == ')') {
10127                                                 if (--arinest == 0) {
10128                                                         USTPUTC(CTLENDARI, out);
10129                                                         syntax = prevsyntax;
10130                                                         dblquote = (syntax == DQSYNTAX);
10131                                                 } else
10132                                                         USTPUTC(')', out);
10133                                         } else {
10134                                                 /*
10135                                                  * unbalanced parens
10136                                                  *  (don't 2nd guess - no error)
10137                                                  */
10138                                                 pungetc();
10139                                                 USTPUTC(')', out);
10140                                         }
10141                                 }
10142                                 break;
10143 #endif
10144                         case CBQUOTE:   /* '`' */
10145                                 PARSEBACKQOLD();
10146                                 break;
10147                         case CENDFILE:
10148                                 goto endword;           /* exit outer loop */
10149                         case CIGN:
10150                                 break;
10151                         default:
10152                                 if (varnest == 0)
10153                                         goto endword;   /* exit outer loop */
10154 #if ENABLE_ASH_ALIAS
10155                                 if (c != PEOA)
10156 #endif
10157                                         USTPUTC(c, out);
10158
10159                         }
10160                         c = pgetc_macro();
10161                 }
10162         }
10163  endword:
10164 #if ENABLE_ASH_MATH_SUPPORT
10165         if (syntax == ARISYNTAX)
10166                 raise_error_syntax("Missing '))'");
10167 #endif
10168         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10169                 raise_error_syntax("Unterminated quoted string");
10170         if (varnest != 0) {
10171                 startlinno = plinno;
10172                 /* { */
10173                 raise_error_syntax("Missing '}'");
10174         }
10175         USTPUTC('\0', out);
10176         len = out - (char *)stackblock();
10177         out = stackblock();
10178         if (eofmark == NULL) {
10179                 if ((c == '>' || c == '<')
10180                  && quotef == 0
10181                  && len <= 2
10182                  && (*out == '\0' || isdigit(*out))) {
10183                         PARSEREDIR();
10184                         return lasttoken = TREDIR;
10185                 } else {
10186                         pungetc();
10187                 }
10188         }
10189         quoteflag = quotef;
10190         backquotelist = bqlist;
10191         grabstackblock(len);
10192         wordtext = out;
10193         lasttoken = TWORD;
10194         return lasttoken;
10195 /* end of readtoken routine */
10196
10197 /*
10198  * Check to see whether we are at the end of the here document.  When this
10199  * is called, c is set to the first character of the next input line.  If
10200  * we are at the end of the here document, this routine sets the c to PEOF.
10201  */
10202 checkend: {
10203         if (eofmark) {
10204 #if ENABLE_ASH_ALIAS
10205                 if (c == PEOA) {
10206                         c = pgetc2();
10207                 }
10208 #endif
10209                 if (striptabs) {
10210                         while (c == '\t') {
10211                                 c = pgetc2();
10212                         }
10213                 }
10214                 if (c == *eofmark) {
10215                         if (pfgets(line, sizeof(line)) != NULL) {
10216                                 char *p, *q;
10217
10218                                 p = line;
10219                                 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10220                                 if (*p == '\n' && *q == '\0') {
10221                                         c = PEOF;
10222                                         plinno++;
10223                                         needprompt = doprompt;
10224                                 } else {
10225                                         pushstring(line, NULL);
10226                                 }
10227                         }
10228                 }
10229         }
10230         goto checkend_return;
10231 }
10232
10233 /*
10234  * Parse a redirection operator.  The variable "out" points to a string
10235  * specifying the fd to be redirected.  The variable "c" contains the
10236  * first character of the redirection operator.
10237  */
10238 parseredir: {
10239         char fd = *out;
10240         union node *np;
10241
10242         np = stalloc(sizeof(struct nfile));
10243         if (c == '>') {
10244                 np->nfile.fd = 1;
10245                 c = pgetc();
10246                 if (c == '>')
10247                         np->type = NAPPEND;
10248                 else if (c == '|')
10249                         np->type = NCLOBBER;
10250                 else if (c == '&')
10251                         np->type = NTOFD;
10252                 else {
10253                         np->type = NTO;
10254                         pungetc();
10255                 }
10256         } else {        /* c == '<' */
10257                 np->nfile.fd = 0;
10258                 c = pgetc();
10259                 switch (c) {
10260                 case '<':
10261                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10262                                 np = stalloc(sizeof(struct nhere));
10263                                 np->nfile.fd = 0;
10264                         }
10265                         np->type = NHERE;
10266                         heredoc = stalloc(sizeof(struct heredoc));
10267                         heredoc->here = np;
10268                         c = pgetc();
10269                         if (c == '-') {
10270                                 heredoc->striptabs = 1;
10271                         } else {
10272                                 heredoc->striptabs = 0;
10273                                 pungetc();
10274                         }
10275                         break;
10276
10277                 case '&':
10278                         np->type = NFROMFD;
10279                         break;
10280
10281                 case '>':
10282                         np->type = NFROMTO;
10283                         break;
10284
10285                 default:
10286                         np->type = NFROM;
10287                         pungetc();
10288                         break;
10289                 }
10290         }
10291         if (fd != '\0')
10292                 np->nfile.fd = fd - '0';
10293         redirnode = np;
10294         goto parseredir_return;
10295 }
10296
10297 /*
10298  * Parse a substitution.  At this point, we have read the dollar sign
10299  * and nothing else.
10300  */
10301
10302 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10303  * (assuming ascii char codes, as the original implementation did) */
10304 #define is_special(c) \
10305         ((((unsigned int)c) - 33 < 32) \
10306                         && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10307 parsesub: {
10308         int subtype;
10309         int typeloc;
10310         int flags;
10311         char *p;
10312         static const char types[] ALIGN1 = "}-+?=";
10313
10314         c = pgetc();
10315         if (
10316                 c <= PEOA_OR_PEOF  ||
10317                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10318         ) {
10319                 USTPUTC('$', out);
10320                 pungetc();
10321         } else if (c == '(') {  /* $(command) or $((arith)) */
10322                 if (pgetc() == '(') {
10323 #if ENABLE_ASH_MATH_SUPPORT
10324                         PARSEARITH();
10325 #else
10326                         raise_error_syntax("We unsupport $((arith))");
10327 #endif
10328                 } else {
10329                         pungetc();
10330                         PARSEBACKQNEW();
10331                 }
10332         } else {
10333                 USTPUTC(CTLVAR, out);
10334                 typeloc = out - (char *)stackblock();
10335                 USTPUTC(VSNORMAL, out);
10336                 subtype = VSNORMAL;
10337                 if (c == '{') {
10338                         c = pgetc();
10339                         if (c == '#') {
10340                                 c = pgetc();
10341                                 if (c == '}')
10342                                         c = '#';
10343                                 else
10344                                         subtype = VSLENGTH;
10345                         } else
10346                                 subtype = 0;
10347                 }
10348                 if (c > PEOA_OR_PEOF && is_name(c)) {
10349                         do {
10350                                 STPUTC(c, out);
10351                                 c = pgetc();
10352                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10353                 } else if (isdigit(c)) {
10354                         do {
10355                                 STPUTC(c, out);
10356                                 c = pgetc();
10357                         } while (isdigit(c));
10358                 } else if (is_special(c)) {
10359                         USTPUTC(c, out);
10360                         c = pgetc();
10361                 } else
10362  badsub:                raise_error_syntax("Bad substitution");
10363
10364                 STPUTC('=', out);
10365                 flags = 0;
10366                 if (subtype == 0) {
10367                         switch (c) {
10368                         case ':':
10369                                 flags = VSNUL;
10370                                 c = pgetc();
10371                                 /*FALLTHROUGH*/
10372                         default:
10373                                 p = strchr(types, c);
10374                                 if (p == NULL)
10375                                         goto badsub;
10376                                 subtype = p - types + VSNORMAL;
10377                                 break;
10378                         case '%':
10379                         case '#':
10380                                 {
10381                                         int cc = c;
10382                                         subtype = c == '#' ? VSTRIMLEFT :
10383                                                              VSTRIMRIGHT;
10384                                         c = pgetc();
10385                                         if (c == cc)
10386                                                 subtype++;
10387                                         else
10388                                                 pungetc();
10389                                         break;
10390                                 }
10391                         }
10392                 } else {
10393                         pungetc();
10394                 }
10395                 if (dblquote || arinest)
10396                         flags |= VSQUOTE;
10397                 *((char *)stackblock() + typeloc) = subtype | flags;
10398                 if (subtype != VSNORMAL) {
10399                         varnest++;
10400                         if (dblquote || arinest) {
10401                                 dqvarnest++;
10402                         }
10403                 }
10404         }
10405         goto parsesub_return;
10406 }
10407
10408 /*
10409  * Called to parse command substitutions.  Newstyle is set if the command
10410  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10411  * list of commands (passed by reference), and savelen is the number of
10412  * characters on the top of the stack which must be preserved.
10413  */
10414 parsebackq: {
10415         struct nodelist **nlpp;
10416         smallint savepbq;
10417         union node *n;
10418         char *volatile str;
10419         struct jmploc jmploc;
10420         struct jmploc *volatile savehandler;
10421         size_t savelen;
10422         smallint saveprompt = 0;
10423
10424 #ifdef __GNUC__
10425         (void) &saveprompt;
10426 #endif
10427         savepbq = parsebackquote;
10428         if (setjmp(jmploc.loc)) {
10429                 free(str);
10430                 parsebackquote = 0;
10431                 exception_handler = savehandler;
10432                 longjmp(exception_handler->loc, 1);
10433         }
10434         INT_OFF;
10435         str = NULL;
10436         savelen = out - (char *)stackblock();
10437         if (savelen > 0) {
10438                 str = ckmalloc(savelen);
10439                 memcpy(str, stackblock(), savelen);
10440         }
10441         savehandler = exception_handler;
10442         exception_handler = &jmploc;
10443         INT_ON;
10444         if (oldstyle) {
10445                 /* We must read until the closing backquote, giving special
10446                    treatment to some slashes, and then push the string and
10447                    reread it as input, interpreting it normally.  */
10448                 char *pout;
10449                 int pc;
10450                 size_t psavelen;
10451                 char *pstr;
10452
10453
10454                 STARTSTACKSTR(pout);
10455                 for (;;) {
10456                         if (needprompt) {
10457                                 setprompt(2);
10458                         }
10459                         pc = pgetc();
10460                         switch (pc) {
10461                         case '`':
10462                                 goto done;
10463
10464                         case '\\':
10465                                 pc = pgetc();
10466                                 if (pc == '\n') {
10467                                         plinno++;
10468                                         if (doprompt)
10469                                                 setprompt(2);
10470                                         /*
10471                                          * If eating a newline, avoid putting
10472                                          * the newline into the new character
10473                                          * stream (via the STPUTC after the
10474                                          * switch).
10475                                          */
10476                                         continue;
10477                                 }
10478                                 if (pc != '\\' && pc != '`' && pc != '$'
10479                                  && (!dblquote || pc != '"'))
10480                                         STPUTC('\\', pout);
10481                                 if (pc > PEOA_OR_PEOF) {
10482                                         break;
10483                                 }
10484                                 /* fall through */
10485
10486                         case PEOF:
10487 #if ENABLE_ASH_ALIAS
10488                         case PEOA:
10489 #endif
10490                                 startlinno = plinno;
10491                                 raise_error_syntax("EOF in backquote substitution");
10492
10493                         case '\n':
10494                                 plinno++;
10495                                 needprompt = doprompt;
10496                                 break;
10497
10498                         default:
10499                                 break;
10500                         }
10501                         STPUTC(pc, pout);
10502                 }
10503  done:
10504                 STPUTC('\0', pout);
10505                 psavelen = pout - (char *)stackblock();
10506                 if (psavelen > 0) {
10507                         pstr = grabstackstr(pout);
10508                         setinputstring(pstr);
10509                 }
10510         }
10511         nlpp = &bqlist;
10512         while (*nlpp)
10513                 nlpp = &(*nlpp)->next;
10514         *nlpp = stalloc(sizeof(**nlpp));
10515         (*nlpp)->next = NULL;
10516         parsebackquote = oldstyle;
10517
10518         if (oldstyle) {
10519                 saveprompt = doprompt;
10520                 doprompt = 0;
10521         }
10522
10523         n = list(2);
10524
10525         if (oldstyle)
10526                 doprompt = saveprompt;
10527         else if (readtoken() != TRP)
10528                 raise_error_unexpected_syntax(TRP);
10529
10530         (*nlpp)->n = n;
10531         if (oldstyle) {
10532                 /*
10533                  * Start reading from old file again, ignoring any pushed back
10534                  * tokens left from the backquote parsing
10535                  */
10536                 popfile();
10537                 tokpushback = 0;
10538         }
10539         while (stackblocksize() <= savelen)
10540                 growstackblock();
10541         STARTSTACKSTR(out);
10542         if (str) {
10543                 memcpy(out, str, savelen);
10544                 STADJUST(savelen, out);
10545                 INT_OFF;
10546                 free(str);
10547                 str = NULL;
10548                 INT_ON;
10549         }
10550         parsebackquote = savepbq;
10551         exception_handler = savehandler;
10552         if (arinest || dblquote)
10553                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10554         else
10555                 USTPUTC(CTLBACKQ, out);
10556         if (oldstyle)
10557                 goto parsebackq_oldreturn;
10558         goto parsebackq_newreturn;
10559 }
10560
10561 #if ENABLE_ASH_MATH_SUPPORT
10562 /*
10563  * Parse an arithmetic expansion (indicate start of one and set state)
10564  */
10565 parsearith: {
10566         if (++arinest == 1) {
10567                 prevsyntax = syntax;
10568                 syntax = ARISYNTAX;
10569                 USTPUTC(CTLARI, out);
10570                 if (dblquote)
10571                         USTPUTC('"', out);
10572                 else
10573                         USTPUTC(' ', out);
10574         } else {
10575                 /*
10576                  * we collapse embedded arithmetic expansion to
10577                  * parenthesis, which should be equivalent
10578                  */
10579                 USTPUTC('(', out);
10580         }
10581         goto parsearith_return;
10582 }
10583 #endif
10584
10585 } /* end of readtoken */
10586
10587 /*
10588  * Read the next input token.
10589  * If the token is a word, we set backquotelist to the list of cmds in
10590  *      backquotes.  We set quoteflag to true if any part of the word was
10591  *      quoted.
10592  * If the token is TREDIR, then we set redirnode to a structure containing
10593  *      the redirection.
10594  * In all cases, the variable startlinno is set to the number of the line
10595  *      on which the token starts.
10596  *
10597  * [Change comment:  here documents and internal procedures]
10598  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10599  *  word parsing code into a separate routine.  In this case, readtoken
10600  *  doesn't need to have any internal procedures, but parseword does.
10601  *  We could also make parseoperator in essence the main routine, and
10602  *  have parseword (readtoken1?) handle both words and redirection.]
10603  */
10604 #define NEW_xxreadtoken
10605 #ifdef NEW_xxreadtoken
10606 /* singles must be first! */
10607 static const char xxreadtoken_chars[7] ALIGN1 = {
10608         '\n', '(', ')', '&', '|', ';', 0
10609 };
10610
10611 static const char xxreadtoken_tokens[] ALIGN1 = {
10612         TNL, TLP, TRP,          /* only single occurrence allowed */
10613         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10614         TEOF,                   /* corresponds to trailing nul */
10615         TAND, TOR, TENDCASE     /* if double occurrence */
10616 };
10617
10618 #define xxreadtoken_doubles \
10619         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10620 #define xxreadtoken_singles \
10621         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10622
10623 static int
10624 xxreadtoken(void)
10625 {
10626         int c;
10627
10628         if (tokpushback) {
10629                 tokpushback = 0;
10630                 return lasttoken;
10631         }
10632         if (needprompt) {
10633                 setprompt(2);
10634         }
10635         startlinno = plinno;
10636         for (;;) {                      /* until token or start of word found */
10637                 c = pgetc_macro();
10638
10639                 if ((c != ' ') && (c != '\t')
10640 #if ENABLE_ASH_ALIAS
10641                  && (c != PEOA)
10642 #endif
10643                 ) {
10644                         if (c == '#') {
10645                                 while ((c = pgetc()) != '\n' && c != PEOF);
10646                                 pungetc();
10647                         } else if (c == '\\') {
10648                                 if (pgetc() != '\n') {
10649                                         pungetc();
10650                                         goto READTOKEN1;
10651                                 }
10652                                 startlinno = ++plinno;
10653                                 if (doprompt)
10654                                         setprompt(2);
10655                         } else {
10656                                 const char *p
10657                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10658
10659                                 if (c != PEOF) {
10660                                         if (c == '\n') {
10661                                                 plinno++;
10662                                                 needprompt = doprompt;
10663                                         }
10664
10665                                         p = strchr(xxreadtoken_chars, c);
10666                                         if (p == NULL) {
10667  READTOKEN1:
10668                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10669                                         }
10670
10671                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10672                                                 if (pgetc() == *p) {    /* double occurrence? */
10673                                                         p += xxreadtoken_doubles + 1;
10674                                                 } else {
10675                                                         pungetc();
10676                                                 }
10677                                         }
10678                                 }
10679                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10680                         }
10681                 }
10682         } /* for */
10683 }
10684 #else
10685 #define RETURN(token)   return lasttoken = token
10686 static int
10687 xxreadtoken(void)
10688 {
10689         int c;
10690
10691         if (tokpushback) {
10692                 tokpushback = 0;
10693                 return lasttoken;
10694         }
10695         if (needprompt) {
10696                 setprompt(2);
10697         }
10698         startlinno = plinno;
10699         for (;;) {      /* until token or start of word found */
10700                 c = pgetc_macro();
10701                 switch (c) {
10702                 case ' ': case '\t':
10703 #if ENABLE_ASH_ALIAS
10704                 case PEOA:
10705 #endif
10706                         continue;
10707                 case '#':
10708                         while ((c = pgetc()) != '\n' && c != PEOF);
10709                         pungetc();
10710                         continue;
10711                 case '\\':
10712                         if (pgetc() == '\n') {
10713                                 startlinno = ++plinno;
10714                                 if (doprompt)
10715                                         setprompt(2);
10716                                 continue;
10717                         }
10718                         pungetc();
10719                         goto breakloop;
10720                 case '\n':
10721                         plinno++;
10722                         needprompt = doprompt;
10723                         RETURN(TNL);
10724                 case PEOF:
10725                         RETURN(TEOF);
10726                 case '&':
10727                         if (pgetc() == '&')
10728                                 RETURN(TAND);
10729                         pungetc();
10730                         RETURN(TBACKGND);
10731                 case '|':
10732                         if (pgetc() == '|')
10733                                 RETURN(TOR);
10734                         pungetc();
10735                         RETURN(TPIPE);
10736                 case ';':
10737                         if (pgetc() == ';')
10738                                 RETURN(TENDCASE);
10739                         pungetc();
10740                         RETURN(TSEMI);
10741                 case '(':
10742                         RETURN(TLP);
10743                 case ')':
10744                         RETURN(TRP);
10745                 default:
10746                         goto breakloop;
10747                 }
10748         }
10749  breakloop:
10750         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10751 #undef RETURN
10752 }
10753 #endif /* NEW_xxreadtoken */
10754
10755 static int
10756 readtoken(void)
10757 {
10758         int t;
10759 #if DEBUG
10760         smallint alreadyseen = tokpushback;
10761 #endif
10762
10763 #if ENABLE_ASH_ALIAS
10764  top:
10765 #endif
10766
10767         t = xxreadtoken();
10768
10769         /*
10770          * eat newlines
10771          */
10772         if (checkkwd & CHKNL) {
10773                 while (t == TNL) {
10774                         parseheredoc();
10775                         t = xxreadtoken();
10776                 }
10777         }
10778
10779         if (t != TWORD || quoteflag) {
10780                 goto out;
10781         }
10782
10783         /*
10784          * check for keywords
10785          */
10786         if (checkkwd & CHKKWD) {
10787                 const char *const *pp;
10788
10789                 pp = findkwd(wordtext);
10790                 if (pp) {
10791                         lasttoken = t = pp - tokname_array;
10792                         TRACE(("keyword %s recognized\n", tokname(t)));
10793                         goto out;
10794                 }
10795         }
10796
10797         if (checkkwd & CHKALIAS) {
10798 #if ENABLE_ASH_ALIAS
10799                 struct alias *ap;
10800                 ap = lookupalias(wordtext, 1);
10801                 if (ap != NULL) {
10802                         if (*ap->val) {
10803                                 pushstring(ap->val, ap);
10804                         }
10805                         goto top;
10806                 }
10807 #endif
10808         }
10809  out:
10810         checkkwd = 0;
10811 #if DEBUG
10812         if (!alreadyseen)
10813                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10814         else
10815                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10816 #endif
10817         return t;
10818 }
10819
10820 static char
10821 peektoken(void)
10822 {
10823         int t;
10824
10825         t = readtoken();
10826         tokpushback = 1;
10827         return tokname_array[t][0];
10828 }
10829
10830 /*
10831  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
10832  * valid parse tree indicating a blank line.)
10833  */
10834 static union node *
10835 parsecmd(int interact)
10836 {
10837         int t;
10838
10839         tokpushback = 0;
10840         doprompt = interact;
10841         if (doprompt)
10842                 setprompt(doprompt);
10843         needprompt = 0;
10844         t = readtoken();
10845         if (t == TEOF)
10846                 return NEOF;
10847         if (t == TNL)
10848                 return NULL;
10849         tokpushback = 1;
10850         return list(1);
10851 }
10852
10853 /*
10854  * Input any here documents.
10855  */
10856 static void
10857 parseheredoc(void)
10858 {
10859         struct heredoc *here;
10860         union node *n;
10861
10862         here = heredoclist;
10863         heredoclist = 0;
10864
10865         while (here) {
10866                 if (needprompt) {
10867                         setprompt(2);
10868                 }
10869                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10870                                 here->eofmark, here->striptabs);
10871                 n = stalloc(sizeof(struct narg));
10872                 n->narg.type = NARG;
10873                 n->narg.next = NULL;
10874                 n->narg.text = wordtext;
10875                 n->narg.backquote = backquotelist;
10876                 here->here->nhere.doc = n;
10877                 here = here->next;
10878         }
10879 }
10880
10881
10882 /*
10883  * called by editline -- any expansions to the prompt should be added here.
10884  */
10885 #if ENABLE_ASH_EXPAND_PRMT
10886 static const char *
10887 expandstr(const char *ps)
10888 {
10889         union node n;
10890
10891         /* XXX Fix (char *) cast. */
10892         setinputstring((char *)ps);
10893         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
10894         popfile();
10895
10896         n.narg.type = NARG;
10897         n.narg.next = NULL;
10898         n.narg.text = wordtext;
10899         n.narg.backquote = backquotelist;
10900
10901         expandarg(&n, NULL, 0);
10902         return stackblock();
10903 }
10904 #endif
10905
10906 /*
10907  * Execute a command or commands contained in a string.
10908  */
10909 static int
10910 evalstring(char *s, int mask)
10911 {
10912         union node *n;
10913         struct stackmark smark;
10914         int skip;
10915
10916         setinputstring(s);
10917         setstackmark(&smark);
10918
10919         skip = 0;
10920         while ((n = parsecmd(0)) != NEOF) {
10921                 evaltree(n, 0);
10922                 popstackmark(&smark);
10923                 skip = evalskip;
10924                 if (skip)
10925                         break;
10926         }
10927         popfile();
10928
10929         skip &= mask;
10930         evalskip = skip;
10931         return skip;
10932 }
10933
10934 /*
10935  * The eval command.
10936  */
10937 static int
10938 evalcmd(int argc, char **argv)
10939 {
10940         char *p;
10941         char *concat;
10942         char **ap;
10943
10944         if (argc > 1) {
10945                 p = argv[1];
10946                 if (argc > 2) {
10947                         STARTSTACKSTR(concat);
10948                         ap = argv + 2;
10949                         for (;;) {
10950                                 concat = stack_putstr(p, concat);
10951                                 p = *ap++;
10952                                 if (p == NULL)
10953                                         break;
10954                                 STPUTC(' ', concat);
10955                         }
10956                         STPUTC('\0', concat);
10957                         p = grabstackstr(concat);
10958                 }
10959                 evalstring(p, ~SKIPEVAL);
10960
10961         }
10962         return exitstatus;
10963 }
10964
10965 /*
10966  * Read and execute commands.  "Top" is nonzero for the top level command
10967  * loop; it turns on prompting if the shell is interactive.
10968  */
10969 static int
10970 cmdloop(int top)
10971 {
10972         union node *n;
10973         struct stackmark smark;
10974         int inter;
10975         int numeof = 0;
10976
10977         TRACE(("cmdloop(%d) called\n", top));
10978         for (;;) {
10979                 int skip;
10980
10981                 setstackmark(&smark);
10982 #if JOBS
10983                 if (jobctl)
10984                         showjobs(stderr, SHOW_CHANGED);
10985 #endif
10986                 inter = 0;
10987                 if (iflag && top) {
10988                         inter++;
10989 #if ENABLE_ASH_MAIL
10990                         chkmail();
10991 #endif
10992                 }
10993                 n = parsecmd(inter);
10994                 /* showtree(n); DEBUG */
10995                 if (n == NEOF) {
10996                         if (!top || numeof >= 50)
10997                                 break;
10998                         if (!stoppedjobs()) {
10999                                 if (!Iflag)
11000                                         break;
11001                                 out2str("\nUse \"exit\" to leave shell.\n");
11002                         }
11003                         numeof++;
11004                 } else if (nflag == 0) {
11005                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11006                         job_warning >>= 1;
11007                         numeof = 0;
11008                         evaltree(n, 0);
11009                 }
11010                 popstackmark(&smark);
11011                 skip = evalskip;
11012
11013                 if (skip) {
11014                         evalskip = 0;
11015                         return skip & SKIPEVAL;
11016                 }
11017         }
11018         return 0;
11019 }
11020
11021 /*
11022  * Take commands from a file.  To be compatible we should do a path
11023  * search for the file, which is necessary to find sub-commands.
11024  */
11025 static char *
11026 find_dot_file(char *name)
11027 {
11028         char *fullname;
11029         const char *path = pathval();
11030         struct stat statb;
11031
11032         /* don't try this for absolute or relative paths */
11033         if (strchr(name, '/'))
11034                 return name;
11035
11036         while ((fullname = padvance(&path, name)) != NULL) {
11037                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11038                         /*
11039                          * Don't bother freeing here, since it will
11040                          * be freed by the caller.
11041                          */
11042                         return fullname;
11043                 }
11044                 stunalloc(fullname);
11045         }
11046
11047         /* not found in the PATH */
11048         ash_msg_and_raise_error("%s: not found", name);
11049         /* NOTREACHED */
11050 }
11051
11052 static int
11053 dotcmd(int argc, char **argv)
11054 {
11055         struct strlist *sp;
11056         volatile struct shparam saveparam;
11057         int status = 0;
11058
11059         for (sp = cmdenviron; sp; sp = sp->next)
11060                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11061
11062         if (argc >= 2) {        /* That's what SVR2 does */
11063                 char *fullname;
11064
11065                 fullname = find_dot_file(argv[1]);
11066
11067                 if (argc > 2) {
11068                         saveparam = shellparam;
11069                         shellparam.malloced = 0;
11070                         shellparam.nparam = argc - 2;
11071                         shellparam.p = argv + 2;
11072                 };
11073
11074                 setinputfile(fullname, INPUT_PUSH_FILE);
11075                 commandname = fullname;
11076                 cmdloop(0);
11077                 popfile();
11078
11079                 if (argc > 2) {
11080                         freeparam(&shellparam);
11081                         shellparam = saveparam;
11082                 };
11083                 status = exitstatus;
11084         }
11085         return status;
11086 }
11087
11088 static int
11089 exitcmd(int argc, char **argv)
11090 {
11091         if (stoppedjobs())
11092                 return 0;
11093         if (argc > 1)
11094                 exitstatus = number(argv[1]);
11095         raise_exception(EXEXIT);
11096         /* NOTREACHED */
11097 }
11098
11099 #if ENABLE_ASH_BUILTIN_ECHO
11100 static int
11101 echocmd(int argc, char **argv)
11102 {
11103         return echo_main(argc, argv);
11104 }
11105 #endif
11106
11107 #if ENABLE_ASH_BUILTIN_TEST
11108 static int
11109 testcmd(int argc, char **argv)
11110 {
11111         return test_main(argc, argv);
11112 }
11113 #endif
11114
11115 /*
11116  * Read a file containing shell functions.
11117  */
11118 static void
11119 readcmdfile(char *name)
11120 {
11121         setinputfile(name, INPUT_PUSH_FILE);
11122         cmdloop(0);
11123         popfile();
11124 }
11125
11126
11127 /* ============ find_command inplementation */
11128
11129 /*
11130  * Resolve a command name.  If you change this routine, you may have to
11131  * change the shellexec routine as well.
11132  */
11133 static void
11134 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11135 {
11136         struct tblentry *cmdp;
11137         int idx;
11138         int prev;
11139         char *fullname;
11140         struct stat statb;
11141         int e;
11142         int updatetbl;
11143         struct builtincmd *bcmd;
11144
11145         /* If name contains a slash, don't use PATH or hash table */
11146         if (strchr(name, '/') != NULL) {
11147                 entry->u.index = -1;
11148                 if (act & DO_ABS) {
11149                         while (stat(name, &statb) < 0) {
11150 #ifdef SYSV
11151                                 if (errno == EINTR)
11152                                         continue;
11153 #endif
11154                                 entry->cmdtype = CMDUNKNOWN;
11155                                 return;
11156                         }
11157                 }
11158                 entry->cmdtype = CMDNORMAL;
11159                 return;
11160         }
11161
11162 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11163
11164         updatetbl = (path == pathval());
11165         if (!updatetbl) {
11166                 act |= DO_ALTPATH;
11167                 if (strstr(path, "%builtin") != NULL)
11168                         act |= DO_ALTBLTIN;
11169         }
11170
11171         /* If name is in the table, check answer will be ok */
11172         cmdp = cmdlookup(name, 0);
11173         if (cmdp != NULL) {
11174                 int bit;
11175
11176                 switch (cmdp->cmdtype) {
11177                 default:
11178 #if DEBUG
11179                         abort();
11180 #endif
11181                 case CMDNORMAL:
11182                         bit = DO_ALTPATH;
11183                         break;
11184                 case CMDFUNCTION:
11185                         bit = DO_NOFUNC;
11186                         break;
11187                 case CMDBUILTIN:
11188                         bit = DO_ALTBLTIN;
11189                         break;
11190                 }
11191                 if (act & bit) {
11192                         updatetbl = 0;
11193                         cmdp = NULL;
11194                 } else if (cmdp->rehash == 0)
11195                         /* if not invalidated by cd, we're done */
11196                         goto success;
11197         }
11198
11199         /* If %builtin not in path, check for builtin next */
11200         bcmd = find_builtin(name);
11201         if (bcmd) {
11202                 if (IS_BUILTIN_REGULAR(bcmd))
11203                         goto builtin_success;
11204                 if (act & DO_ALTPATH) {
11205                         if (!(act & DO_ALTBLTIN))
11206                                 goto builtin_success;
11207                 } else if (builtinloc <= 0) {
11208                         goto builtin_success;
11209                 }
11210         }
11211
11212 #if ENABLE_FEATURE_SH_STANDALONE
11213         if (find_applet_by_name(name) >= 0) {
11214                 entry->cmdtype = CMDNORMAL;
11215                 entry->u.index = -1;
11216                 return;
11217         }
11218 #endif
11219
11220         /* We have to search path. */
11221         prev = -1;              /* where to start */
11222         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11223                 if (cmdp->cmdtype == CMDBUILTIN)
11224                         prev = builtinloc;
11225                 else
11226                         prev = cmdp->param.index;
11227         }
11228
11229         e = ENOENT;
11230         idx = -1;
11231  loop:
11232         while ((fullname = padvance(&path, name)) != NULL) {
11233                 stunalloc(fullname);
11234                 /* NB: code below will still use fullname
11235                  * despite it being "unallocated" */
11236                 idx++;
11237                 if (pathopt) {
11238                         if (prefix(pathopt, "builtin")) {
11239                                 if (bcmd)
11240                                         goto builtin_success;
11241                                 continue;
11242                         } else if (!(act & DO_NOFUNC)
11243                          && prefix(pathopt, "func")) {
11244                                 /* handled below */
11245                         } else {
11246                                 /* ignore unimplemented options */
11247                                 continue;
11248                         }
11249                 }
11250                 /* if rehash, don't redo absolute path names */
11251                 if (fullname[0] == '/' && idx <= prev) {
11252                         if (idx < prev)
11253                                 continue;
11254                         TRACE(("searchexec \"%s\": no change\n", name));
11255                         goto success;
11256                 }
11257                 while (stat(fullname, &statb) < 0) {
11258 #ifdef SYSV
11259                         if (errno == EINTR)
11260                                 continue;
11261 #endif
11262                         if (errno != ENOENT && errno != ENOTDIR)
11263                                 e = errno;
11264                         goto loop;
11265                 }
11266                 e = EACCES;     /* if we fail, this will be the error */
11267                 if (!S_ISREG(statb.st_mode))
11268                         continue;
11269                 if (pathopt) {          /* this is a %func directory */
11270                         stalloc(strlen(fullname) + 1);
11271                         /* NB: stalloc will return space pointed by fullname
11272                          * (because we don't have any intervening allocations
11273                          * between stunalloc above and this stalloc) */
11274                         readcmdfile(fullname);
11275                         cmdp = cmdlookup(name, 0);
11276                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11277                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11278                         stunalloc(fullname);
11279                         goto success;
11280                 }
11281                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11282                 if (!updatetbl) {
11283                         entry->cmdtype = CMDNORMAL;
11284                         entry->u.index = idx;
11285                         return;
11286                 }
11287                 INT_OFF;
11288                 cmdp = cmdlookup(name, 1);
11289                 cmdp->cmdtype = CMDNORMAL;
11290                 cmdp->param.index = idx;
11291                 INT_ON;
11292                 goto success;
11293         }
11294
11295         /* We failed.  If there was an entry for this command, delete it */
11296         if (cmdp && updatetbl)
11297                 delete_cmd_entry();
11298         if (act & DO_ERR)
11299                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11300         entry->cmdtype = CMDUNKNOWN;
11301         return;
11302
11303  builtin_success:
11304         if (!updatetbl) {
11305                 entry->cmdtype = CMDBUILTIN;
11306                 entry->u.cmd = bcmd;
11307                 return;
11308         }
11309         INT_OFF;
11310         cmdp = cmdlookup(name, 1);
11311         cmdp->cmdtype = CMDBUILTIN;
11312         cmdp->param.cmd = bcmd;
11313         INT_ON;
11314  success:
11315         cmdp->rehash = 0;
11316         entry->cmdtype = cmdp->cmdtype;
11317         entry->u = cmdp->param;
11318 }
11319
11320
11321 /* ============ trap.c */
11322
11323 /*
11324  * The trap builtin.
11325  */
11326 static int
11327 trapcmd(int argc, char **argv)
11328 {
11329         char *action;
11330         char **ap;
11331         int signo;
11332
11333         nextopt(nullstr);
11334         ap = argptr;
11335         if (!*ap) {
11336                 for (signo = 0; signo < NSIG; signo++) {
11337                         if (trap[signo] != NULL) {
11338                                 const char *sn;
11339
11340                                 sn = get_signame(signo);
11341                                 out1fmt("trap -- %s %s\n",
11342                                         single_quote(trap[signo]), sn);
11343                         }
11344                 }
11345                 return 0;
11346         }
11347         if (!ap[1])
11348                 action = NULL;
11349         else
11350                 action = *ap++;
11351         while (*ap) {
11352                 signo = get_signum(*ap);
11353                 if (signo < 0)
11354                         ash_msg_and_raise_error("%s: bad trap", *ap);
11355                 INT_OFF;
11356                 if (action) {
11357                         if (LONE_DASH(action))
11358                                 action = NULL;
11359                         else
11360                                 action = ckstrdup(action);
11361                 }
11362                 free(trap[signo]);
11363                 trap[signo] = action;
11364                 if (signo != 0)
11365                         setsignal(signo);
11366                 INT_ON;
11367                 ap++;
11368         }
11369         return 0;
11370 }
11371
11372
11373 /* ============ Builtins */
11374
11375 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11376 /*
11377  * Lists available builtins
11378  */
11379 static int
11380 helpcmd(int argc, char **argv)
11381 {
11382         int col, i;
11383
11384         out1fmt("\nBuilt-in commands:\n-------------------\n");
11385         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11386                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11387                                         builtintab[i].name + 1);
11388                 if (col > 60) {
11389                         out1fmt("\n");
11390                         col = 0;
11391                 }
11392         }
11393 #if ENABLE_FEATURE_SH_STANDALONE
11394         {
11395                 const char *a = applet_names;
11396                 while (*a) {
11397                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11398                         if (col > 60) {
11399                                 out1fmt("\n");
11400                                 col = 0;
11401                         }
11402                         a += strlen(a) + 1;
11403                 }
11404         }
11405 #endif
11406         out1fmt("\n\n");
11407         return EXIT_SUCCESS;
11408 }
11409 #endif /* FEATURE_SH_EXTRA_QUIET */
11410
11411 /*
11412  * The export and readonly commands.
11413  */
11414 static int
11415 exportcmd(int argc, char **argv)
11416 {
11417         struct var *vp;
11418         char *name;
11419         const char *p;
11420         char **aptr;
11421         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11422
11423         if (nextopt("p") != 'p') {
11424                 aptr = argptr;
11425                 name = *aptr;
11426                 if (name) {
11427                         do {
11428                                 p = strchr(name, '=');
11429                                 if (p != NULL) {
11430                                         p++;
11431                                 } else {
11432                                         vp = *findvar(hashvar(name), name);
11433                                         if (vp) {
11434                                                 vp->flags |= flag;
11435                                                 continue;
11436                                         }
11437                                 }
11438                                 setvar(name, p, flag);
11439                         } while ((name = *++aptr) != NULL);
11440                         return 0;
11441                 }
11442         }
11443         showvars(argv[0], flag, 0);
11444         return 0;
11445 }
11446
11447 /*
11448  * Delete a function if it exists.
11449  */
11450 static void
11451 unsetfunc(const char *name)
11452 {
11453         struct tblentry *cmdp;
11454
11455         cmdp = cmdlookup(name, 0);
11456         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11457                 delete_cmd_entry();
11458 }
11459
11460 /*
11461  * The unset builtin command.  We unset the function before we unset the
11462  * variable to allow a function to be unset when there is a readonly variable
11463  * with the same name.
11464  */
11465 static int
11466 unsetcmd(int argc, char **argv)
11467 {
11468         char **ap;
11469         int i;
11470         int flag = 0;
11471         int ret = 0;
11472
11473         while ((i = nextopt("vf")) != '\0') {
11474                 flag = i;
11475         }
11476
11477         for (ap = argptr; *ap; ap++) {
11478                 if (flag != 'f') {
11479                         i = unsetvar(*ap);
11480                         ret |= i;
11481                         if (!(i & 2))
11482                                 continue;
11483                 }
11484                 if (flag != 'v')
11485                         unsetfunc(*ap);
11486         }
11487         return ret & 1;
11488 }
11489
11490
11491 /*      setmode.c      */
11492
11493 #include <sys/times.h>
11494
11495 static const unsigned char timescmd_str[] ALIGN1 = {
11496         ' ',  offsetof(struct tms, tms_utime),
11497         '\n', offsetof(struct tms, tms_stime),
11498         ' ',  offsetof(struct tms, tms_cutime),
11499         '\n', offsetof(struct tms, tms_cstime),
11500         0
11501 };
11502
11503 static int
11504 timescmd(int ac, char **av)
11505 {
11506         long clk_tck, s, t;
11507         const unsigned char *p;
11508         struct tms buf;
11509
11510         clk_tck = sysconf(_SC_CLK_TCK);
11511         times(&buf);
11512
11513         p = timescmd_str;
11514         do {
11515                 t = *(clock_t *)(((char *) &buf) + p[1]);
11516                 s = t / clk_tck;
11517                 out1fmt("%ldm%ld.%.3lds%c",
11518                         s/60, s%60,
11519                         ((t - s * clk_tck) * 1000) / clk_tck,
11520                         p[0]);
11521         } while (*(p += 2));
11522
11523         return 0;
11524 }
11525
11526 #if ENABLE_ASH_MATH_SUPPORT
11527 static arith_t
11528 dash_arith(const char *s)
11529 {
11530         arith_t result;
11531         int errcode = 0;
11532
11533         INT_OFF;
11534         result = arith(s, &errcode);
11535         if (errcode < 0) {
11536                 if (errcode == -3)
11537                         ash_msg_and_raise_error("exponent less than 0");
11538                 if (errcode == -2)
11539                         ash_msg_and_raise_error("divide by zero");
11540                 if (errcode == -5)
11541                         ash_msg_and_raise_error("expression recursion loop detected");
11542                 raise_error_syntax(s);
11543         }
11544         INT_ON;
11545
11546         return result;
11547 }
11548
11549 /*
11550  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11551  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11552  *
11553  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11554  */
11555 static int
11556 letcmd(int argc, char **argv)
11557 {
11558         char **ap;
11559         arith_t i = 0;
11560
11561         ap = argv + 1;
11562         if (!*ap)
11563                 ash_msg_and_raise_error("expression expected");
11564         for (ap = argv + 1; *ap; ap++) {
11565                 i = dash_arith(*ap);
11566         }
11567
11568         return !i;
11569 }
11570 #endif /* ASH_MATH_SUPPORT */
11571
11572
11573 /* ============ miscbltin.c
11574  *
11575  * Miscellaneous builtins.
11576  */
11577
11578 #undef rflag
11579
11580 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11581 typedef enum __rlimit_resource rlim_t;
11582 #endif
11583
11584 /*
11585  * The read builtin.  The -e option causes backslashes to escape the
11586  * following character.
11587  *
11588  * This uses unbuffered input, which may be avoidable in some cases.
11589  */
11590 static int
11591 readcmd(int argc, char **argv)
11592 {
11593         char **ap;
11594         int backslash;
11595         char c;
11596         int rflag;
11597         char *prompt;
11598         const char *ifs;
11599         char *p;
11600         int startword;
11601         int status;
11602         int i;
11603 #if ENABLE_ASH_READ_NCHARS
11604         int n_flag = 0;
11605         int nchars = 0;
11606         int silent = 0;
11607         struct termios tty, old_tty;
11608 #endif
11609 #if ENABLE_ASH_READ_TIMEOUT
11610         fd_set set;
11611         struct timeval ts;
11612
11613         ts.tv_sec = ts.tv_usec = 0;
11614 #endif
11615
11616         rflag = 0;
11617         prompt = NULL;
11618 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11619         while ((i = nextopt("p:rt:n:s")) != '\0')
11620 #elif ENABLE_ASH_READ_NCHARS
11621         while ((i = nextopt("p:rn:s")) != '\0')
11622 #elif ENABLE_ASH_READ_TIMEOUT
11623         while ((i = nextopt("p:rt:")) != '\0')
11624 #else
11625         while ((i = nextopt("p:r")) != '\0')
11626 #endif
11627         {
11628                 switch (i) {
11629                 case 'p':
11630                         prompt = optionarg;
11631                         break;
11632 #if ENABLE_ASH_READ_NCHARS
11633                 case 'n':
11634                         nchars = bb_strtou(optionarg, NULL, 10);
11635                         if (nchars < 0 || errno)
11636                                 ash_msg_and_raise_error("invalid count");
11637                         n_flag = nchars; /* just a flag "nchars is nonzero" */
11638                         break;
11639                 case 's':
11640                         silent = 1;
11641                         break;
11642 #endif
11643 #if ENABLE_ASH_READ_TIMEOUT
11644                 case 't':
11645                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
11646                         ts.tv_usec = 0;
11647                         /* EINVAL means number is ok, but not terminated by NUL */
11648                         if (*p == '.' && errno == EINVAL) {
11649                                 char *p2;
11650                                 if (*++p) {
11651                                         int scale;
11652                                         ts.tv_usec = bb_strtou(p, &p2, 10);
11653                                         if (errno)
11654                                                 ash_msg_and_raise_error("invalid timeout");
11655                                         scale = p2 - p;
11656                                         /* normalize to usec */
11657                                         if (scale > 6)
11658                                                 ash_msg_and_raise_error("invalid timeout");
11659                                         while (scale++ < 6)
11660                                                 ts.tv_usec *= 10;
11661                                 }
11662                         } else if (ts.tv_sec < 0 || errno) {
11663                                 ash_msg_and_raise_error("invalid timeout");
11664                         }
11665                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
11666                                 ash_msg_and_raise_error("invalid timeout");
11667                         }
11668                         break;
11669 #endif
11670                 case 'r':
11671                         rflag = 1;
11672                         break;
11673                 default:
11674                         break;
11675                 }
11676         }
11677         if (prompt && isatty(0)) {
11678                 out2str(prompt);
11679         }
11680         ap = argptr;
11681         if (*ap == NULL)
11682                 ash_msg_and_raise_error("arg count");
11683         ifs = bltinlookup("IFS");
11684         if (ifs == NULL)
11685                 ifs = defifs;
11686 #if ENABLE_ASH_READ_NCHARS
11687         if (n_flag || silent) {
11688                 if (tcgetattr(0, &tty) != 0) {
11689                         /* Not a tty */
11690                         n_flag = 0;
11691                         silent = 0;
11692                 } else {
11693                         old_tty = tty;
11694                         if (n_flag) {
11695                                 tty.c_lflag &= ~ICANON;
11696                                 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
11697                         }
11698                         if (silent) {
11699                                 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
11700                         }
11701                         tcsetattr(0, TCSANOW, &tty);
11702                 }
11703         }
11704 #endif
11705 #if ENABLE_ASH_READ_TIMEOUT
11706         if (ts.tv_sec || ts.tv_usec) {
11707                 FD_ZERO(&set);
11708                 FD_SET(0, &set);
11709
11710                 /* poll-based wait produces bigger code, using select */
11711                 i = select(1, &set, NULL, NULL, &ts);
11712                 if (!i) { /* timed out! */
11713 #if ENABLE_ASH_READ_NCHARS
11714                         if (n_flag)
11715                                 tcsetattr(0, TCSANOW, &old_tty);
11716 #endif
11717                         return 1;
11718                 }
11719         }
11720 #endif
11721         status = 0;
11722         startword = 1;
11723         backslash = 0;
11724         STARTSTACKSTR(p);
11725         do {
11726                 if (read(0, &c, 1) != 1) {
11727                         status = 1;
11728                         break;
11729                 }
11730                 if (c == '\0')
11731                         continue;
11732                 if (backslash) {
11733                         backslash = 0;
11734                         if (c != '\n')
11735                                 goto put;
11736                         continue;
11737                 }
11738                 if (!rflag && c == '\\') {
11739                         backslash++;
11740                         continue;
11741                 }
11742                 if (c == '\n')
11743                         break;
11744                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11745                         continue;
11746                 }
11747                 startword = 0;
11748                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11749                         STACKSTRNUL(p);
11750                         setvar(*ap, stackblock(), 0);
11751                         ap++;
11752                         startword = 1;
11753                         STARTSTACKSTR(p);
11754                 } else {
11755  put:
11756                         STPUTC(c, p);
11757                 }
11758         }
11759 /* end of do {} while: */
11760 #if ENABLE_ASH_READ_NCHARS
11761         while (!n_flag || --nchars);
11762 #else
11763         while (1);
11764 #endif
11765
11766 #if ENABLE_ASH_READ_NCHARS
11767         if (n_flag || silent)
11768                 tcsetattr(0, TCSANOW, &old_tty);
11769 #endif
11770
11771         STACKSTRNUL(p);
11772         /* Remove trailing blanks */
11773         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11774                 *p = '\0';
11775         setvar(*ap, stackblock(), 0);
11776         while (*++ap != NULL)
11777                 setvar(*ap, nullstr, 0);
11778         return status;
11779 }
11780
11781 static int
11782 umaskcmd(int argc, char **argv)
11783 {
11784         static const char permuser[3] ALIGN1 = "ugo";
11785         static const char permmode[3] ALIGN1 = "rwx";
11786         static const short permmask[] ALIGN2 = {
11787                 S_IRUSR, S_IWUSR, S_IXUSR,
11788                 S_IRGRP, S_IWGRP, S_IXGRP,
11789                 S_IROTH, S_IWOTH, S_IXOTH
11790         };
11791
11792         char *ap;
11793         mode_t mask;
11794         int i;
11795         int symbolic_mode = 0;
11796
11797         while (nextopt("S") != '\0') {
11798                 symbolic_mode = 1;
11799         }
11800
11801         INT_OFF;
11802         mask = umask(0);
11803         umask(mask);
11804         INT_ON;
11805
11806         ap = *argptr;
11807         if (ap == NULL) {
11808                 if (symbolic_mode) {
11809                         char buf[18];
11810                         char *p = buf;
11811
11812                         for (i = 0; i < 3; i++) {
11813                                 int j;
11814
11815                                 *p++ = permuser[i];
11816                                 *p++ = '=';
11817                                 for (j = 0; j < 3; j++) {
11818                                         if ((mask & permmask[3 * i + j]) == 0) {
11819                                                 *p++ = permmode[j];
11820                                         }
11821                                 }
11822                                 *p++ = ',';
11823                         }
11824                         *--p = 0;
11825                         puts(buf);
11826                 } else {
11827                         out1fmt("%.4o\n", mask);
11828                 }
11829         } else {
11830                 if (isdigit((unsigned char) *ap)) {
11831                         mask = 0;
11832                         do {
11833                                 if (*ap >= '8' || *ap < '0')
11834                                         ash_msg_and_raise_error(illnum, argv[1]);
11835                                 mask = (mask << 3) + (*ap - '0');
11836                         } while (*++ap != '\0');
11837                         umask(mask);
11838                 } else {
11839                         mask = ~mask & 0777;
11840                         if (!bb_parse_mode(ap, &mask)) {
11841                                 ash_msg_and_raise_error("illegal mode: %s", ap);
11842                         }
11843                         umask(~mask & 0777);
11844                 }
11845         }
11846         return 0;
11847 }
11848
11849 /*
11850  * ulimit builtin
11851  *
11852  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11853  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11854  * ash by J.T. Conklin.
11855  *
11856  * Public domain.
11857  */
11858
11859 struct limits {
11860         uint8_t cmd;          /* RLIMIT_xxx fit into it */
11861         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
11862         char    option;
11863 };
11864
11865 static const struct limits limits_tbl[] = {
11866 #ifdef RLIMIT_CPU
11867         { RLIMIT_CPU,        0, 't' },
11868 #endif
11869 #ifdef RLIMIT_FSIZE
11870         { RLIMIT_FSIZE,      9, 'f' },
11871 #endif
11872 #ifdef RLIMIT_DATA
11873         { RLIMIT_DATA,      10, 'd' },
11874 #endif
11875 #ifdef RLIMIT_STACK
11876         { RLIMIT_STACK,     10, 's' },
11877 #endif
11878 #ifdef RLIMIT_CORE
11879         { RLIMIT_CORE,       9, 'c' },
11880 #endif
11881 #ifdef RLIMIT_RSS
11882         { RLIMIT_RSS,       10, 'm' },
11883 #endif
11884 #ifdef RLIMIT_MEMLOCK
11885         { RLIMIT_MEMLOCK,   10, 'l' },
11886 #endif
11887 #ifdef RLIMIT_NPROC
11888         { RLIMIT_NPROC,      0, 'p' },
11889 #endif
11890 #ifdef RLIMIT_NOFILE
11891         { RLIMIT_NOFILE,     0, 'n' },
11892 #endif
11893 #ifdef RLIMIT_AS
11894         { RLIMIT_AS,        10, 'v' },
11895 #endif
11896 #ifdef RLIMIT_LOCKS
11897         { RLIMIT_LOCKS,      0, 'w' },
11898 #endif
11899 };
11900 static const char limits_name[] =
11901 #ifdef RLIMIT_CPU
11902         "time(seconds)" "\0"
11903 #endif
11904 #ifdef RLIMIT_FSIZE
11905         "file(blocks)" "\0"
11906 #endif
11907 #ifdef RLIMIT_DATA
11908         "data(kb)" "\0"
11909 #endif
11910 #ifdef RLIMIT_STACK
11911         "stack(kb)" "\0"
11912 #endif
11913 #ifdef RLIMIT_CORE
11914         "coredump(blocks)" "\0"
11915 #endif
11916 #ifdef RLIMIT_RSS
11917         "memory(kb)" "\0"
11918 #endif
11919 #ifdef RLIMIT_MEMLOCK
11920         "locked memory(kb)" "\0"
11921 #endif
11922 #ifdef RLIMIT_NPROC
11923         "process" "\0"
11924 #endif
11925 #ifdef RLIMIT_NOFILE
11926         "nofiles" "\0"
11927 #endif
11928 #ifdef RLIMIT_AS
11929         "vmemory(kb)" "\0"
11930 #endif
11931 #ifdef RLIMIT_LOCKS
11932         "locks" "\0"
11933 #endif
11934 ;
11935
11936 enum limtype { SOFT = 0x1, HARD = 0x2 };
11937
11938 static void
11939 printlim(enum limtype how, const struct rlimit *limit,
11940                         const struct limits *l)
11941 {
11942         rlim_t val;
11943
11944         val = limit->rlim_max;
11945         if (how & SOFT)
11946                 val = limit->rlim_cur;
11947
11948         if (val == RLIM_INFINITY)
11949                 out1fmt("unlimited\n");
11950         else {
11951                 val >>= l->factor_shift;
11952                 out1fmt("%lld\n", (long long) val);
11953         }
11954 }
11955
11956 static int
11957 ulimitcmd(int argc, char **argv)
11958 {
11959         int c;
11960         rlim_t val = 0;
11961         enum limtype how = SOFT | HARD;
11962         const struct limits *l;
11963         int set, all = 0;
11964         int optc, what;
11965         struct rlimit limit;
11966
11967         what = 'f';
11968         while ((optc = nextopt("HSa"
11969 #ifdef RLIMIT_CPU
11970                                 "t"
11971 #endif
11972 #ifdef RLIMIT_FSIZE
11973                                 "f"
11974 #endif
11975 #ifdef RLIMIT_DATA
11976                                 "d"
11977 #endif
11978 #ifdef RLIMIT_STACK
11979                                 "s"
11980 #endif
11981 #ifdef RLIMIT_CORE
11982                                 "c"
11983 #endif
11984 #ifdef RLIMIT_RSS
11985                                 "m"
11986 #endif
11987 #ifdef RLIMIT_MEMLOCK
11988                                 "l"
11989 #endif
11990 #ifdef RLIMIT_NPROC
11991                                 "p"
11992 #endif
11993 #ifdef RLIMIT_NOFILE
11994                                 "n"
11995 #endif
11996 #ifdef RLIMIT_AS
11997                                 "v"
11998 #endif
11999 #ifdef RLIMIT_LOCKS
12000                                 "w"
12001 #endif
12002                                         )) != '\0')
12003                 switch (optc) {
12004                 case 'H':
12005                         how = HARD;
12006                         break;
12007                 case 'S':
12008                         how = SOFT;
12009                         break;
12010                 case 'a':
12011                         all = 1;
12012                         break;
12013                 default:
12014                         what = optc;
12015                 }
12016
12017         for (l = limits_tbl; l->option != what; l++)
12018                 continue;
12019
12020         set = *argptr ? 1 : 0;
12021         if (set) {
12022                 char *p = *argptr;
12023
12024                 if (all || argptr[1])
12025                         ash_msg_and_raise_error("too many arguments");
12026                 if (strncmp(p, "unlimited\n", 9) == 0)
12027                         val = RLIM_INFINITY;
12028                 else {
12029                         val = (rlim_t) 0;
12030
12031                         while ((c = *p++) >= '0' && c <= '9') {
12032                                 val = (val * 10) + (long)(c - '0');
12033                                 if (val < (rlim_t) 0)
12034                                         break;
12035                         }
12036                         if (c)
12037                                 ash_msg_and_raise_error("bad number");
12038                         val <<= l->factor_shift;
12039                 }
12040         }
12041         if (all) {
12042                 const char *lname = limits_name;
12043                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12044                         getrlimit(l->cmd, &limit);
12045                         out1fmt("%-20s ", lname);
12046                         lname += strlen(lname) + 1;
12047                         printlim(how, &limit, l);
12048                 }
12049                 return 0;
12050         }
12051
12052         getrlimit(l->cmd, &limit);
12053         if (set) {
12054                 if (how & HARD)
12055                         limit.rlim_max = val;
12056                 if (how & SOFT)
12057                         limit.rlim_cur = val;
12058                 if (setrlimit(l->cmd, &limit) < 0)
12059                         ash_msg_and_raise_error("error setting limit (%m)");
12060         } else {
12061                 printlim(how, &limit, l);
12062         }
12063         return 0;
12064 }
12065
12066
12067 /* ============ Math support */
12068
12069 #if ENABLE_ASH_MATH_SUPPORT
12070
12071 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12072
12073    Permission is hereby granted, free of charge, to any person obtaining
12074    a copy of this software and associated documentation files (the
12075    "Software"), to deal in the Software without restriction, including
12076    without limitation the rights to use, copy, modify, merge, publish,
12077    distribute, sublicense, and/or sell copies of the Software, and to
12078    permit persons to whom the Software is furnished to do so, subject to
12079    the following conditions:
12080
12081    The above copyright notice and this permission notice shall be
12082    included in all copies or substantial portions of the Software.
12083
12084    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12085    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12086    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12087    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12088    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12089    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12090    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12091 */
12092
12093 /* This is my infix parser/evaluator. It is optimized for size, intended
12094  * as a replacement for yacc-based parsers. However, it may well be faster
12095  * than a comparable parser written in yacc. The supported operators are
12096  * listed in #defines below. Parens, order of operations, and error handling
12097  * are supported. This code is thread safe. The exact expression format should
12098  * be that which POSIX specifies for shells. */
12099
12100 /* The code uses a simple two-stack algorithm. See
12101  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12102  * for a detailed explanation of the infix-to-postfix algorithm on which
12103  * this is based (this code differs in that it applies operators immediately
12104  * to the stack instead of adding them to a queue to end up with an
12105  * expression). */
12106
12107 /* To use the routine, call it with an expression string and error return
12108  * pointer */
12109
12110 /*
12111  * Aug 24, 2001              Manuel Novoa III
12112  *
12113  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12114  *
12115  * 1) In arith_apply():
12116  *    a) Cached values of *numptr and &(numptr[-1]).
12117  *    b) Removed redundant test for zero denominator.
12118  *
12119  * 2) In arith():
12120  *    a) Eliminated redundant code for processing operator tokens by moving
12121  *       to a table-based implementation.  Also folded handling of parens
12122  *       into the table.
12123  *    b) Combined all 3 loops which called arith_apply to reduce generated
12124  *       code size at the cost of speed.
12125  *
12126  * 3) The following expressions were treated as valid by the original code:
12127  *       1()  ,    0!  ,    1 ( *3 )   .
12128  *    These bugs have been fixed by internally enclosing the expression in
12129  *    parens and then checking that all binary ops and right parens are
12130  *    preceded by a valid expression (NUM_TOKEN).
12131  *
12132  * Note: It may be desirable to replace Aaron's test for whitespace with
12133  * ctype's isspace() if it is used by another busybox applet or if additional
12134  * whitespace chars should be considered.  Look below the "#include"s for a
12135  * precompiler test.
12136  */
12137
12138 /*
12139  * Aug 26, 2001              Manuel Novoa III
12140  *
12141  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12142  *
12143  * Merge in Aaron's comments previously posted to the busybox list,
12144  * modified slightly to take account of my changes to the code.
12145  *
12146  */
12147
12148 /*
12149  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12150  *
12151  * - allow access to variable,
12152  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12153  * - realize assign syntax (VAR=expr, +=, *= etc)
12154  * - realize exponentiation (** operator)
12155  * - realize comma separated - expr, expr
12156  * - realise ++expr --expr expr++ expr--
12157  * - realise expr ? expr : expr (but, second expr calculate always)
12158  * - allow hexadecimal and octal numbers
12159  * - was restored loses XOR operator
12160  * - remove one goto label, added three ;-)
12161  * - protect $((num num)) as true zero expr (Manuel`s error)
12162  * - always use special isspace(), see comment from bash ;-)
12163  */
12164
12165 #define arith_isspace(arithval) \
12166         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12167
12168 typedef unsigned char operator;
12169
12170 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12171  * precedence, and 3 high bits are an ID unique across operators of that
12172  * precedence. The ID portion is so that multiple operators can have the
12173  * same precedence, ensuring that the leftmost one is evaluated first.
12174  * Consider * and /. */
12175
12176 #define tok_decl(prec,id) (((id)<<5)|(prec))
12177 #define PREC(op) ((op) & 0x1F)
12178
12179 #define TOK_LPAREN tok_decl(0,0)
12180
12181 #define TOK_COMMA tok_decl(1,0)
12182
12183 #define TOK_ASSIGN tok_decl(2,0)
12184 #define TOK_AND_ASSIGN tok_decl(2,1)
12185 #define TOK_OR_ASSIGN tok_decl(2,2)
12186 #define TOK_XOR_ASSIGN tok_decl(2,3)
12187 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12188 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12189 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12190 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12191
12192 #define TOK_MUL_ASSIGN tok_decl(3,0)
12193 #define TOK_DIV_ASSIGN tok_decl(3,1)
12194 #define TOK_REM_ASSIGN tok_decl(3,2)
12195
12196 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12197 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12198
12199 /* conditional is right associativity too */
12200 #define TOK_CONDITIONAL tok_decl(4,0)
12201 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12202
12203 #define TOK_OR tok_decl(5,0)
12204
12205 #define TOK_AND tok_decl(6,0)
12206
12207 #define TOK_BOR tok_decl(7,0)
12208
12209 #define TOK_BXOR tok_decl(8,0)
12210
12211 #define TOK_BAND tok_decl(9,0)
12212
12213 #define TOK_EQ tok_decl(10,0)
12214 #define TOK_NE tok_decl(10,1)
12215
12216 #define TOK_LT tok_decl(11,0)
12217 #define TOK_GT tok_decl(11,1)
12218 #define TOK_GE tok_decl(11,2)
12219 #define TOK_LE tok_decl(11,3)
12220
12221 #define TOK_LSHIFT tok_decl(12,0)
12222 #define TOK_RSHIFT tok_decl(12,1)
12223
12224 #define TOK_ADD tok_decl(13,0)
12225 #define TOK_SUB tok_decl(13,1)
12226
12227 #define TOK_MUL tok_decl(14,0)
12228 #define TOK_DIV tok_decl(14,1)
12229 #define TOK_REM tok_decl(14,2)
12230
12231 /* exponent is right associativity */
12232 #define TOK_EXPONENT tok_decl(15,1)
12233
12234 /* For now unary operators. */
12235 #define UNARYPREC 16
12236 #define TOK_BNOT tok_decl(UNARYPREC,0)
12237 #define TOK_NOT tok_decl(UNARYPREC,1)
12238
12239 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12240 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12241
12242 #define PREC_PRE (UNARYPREC+2)
12243
12244 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12245 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12246
12247 #define PREC_POST (UNARYPREC+3)
12248
12249 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12250 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12251
12252 #define SPEC_PREC (UNARYPREC+4)
12253
12254 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12255 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12256
12257 #define NUMPTR (*numstackptr)
12258
12259 static int
12260 tok_have_assign(operator op)
12261 {
12262         operator prec = PREC(op);
12263
12264         convert_prec_is_assing(prec);
12265         return (prec == PREC(TOK_ASSIGN) ||
12266                         prec == PREC_PRE || prec == PREC_POST);
12267 }
12268
12269 static int
12270 is_right_associativity(operator prec)
12271 {
12272         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12273                 || prec == PREC(TOK_CONDITIONAL));
12274 }
12275
12276 typedef struct ARITCH_VAR_NUM {
12277         arith_t val;
12278         arith_t contidional_second_val;
12279         char contidional_second_val_initialized;
12280         char *var;      /* if NULL then is regular number,
12281                            else is variable name */
12282 } v_n_t;
12283
12284 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12285         const char *var;
12286         struct CHK_VAR_RECURSIVE_LOOPED *next;
12287 } chk_var_recursive_looped_t;
12288
12289 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12290
12291 static int
12292 arith_lookup_val(v_n_t *t)
12293 {
12294         if (t->var) {
12295                 const char * p = lookupvar(t->var);
12296
12297                 if (p) {
12298                         int errcode;
12299
12300                         /* recursive try as expression */
12301                         chk_var_recursive_looped_t *cur;
12302                         chk_var_recursive_looped_t cur_save;
12303
12304                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12305                                 if (strcmp(cur->var, t->var) == 0) {
12306                                         /* expression recursion loop detected */
12307                                         return -5;
12308                                 }
12309                         }
12310                         /* save current lookuped var name */
12311                         cur = prev_chk_var_recursive;
12312                         cur_save.var = t->var;
12313                         cur_save.next = cur;
12314                         prev_chk_var_recursive = &cur_save;
12315
12316                         t->val = arith (p, &errcode);
12317                         /* restore previous ptr after recursiving */
12318                         prev_chk_var_recursive = cur;
12319                         return errcode;
12320                 }
12321                 /* allow undefined var as 0 */
12322                 t->val = 0;
12323         }
12324         return 0;
12325 }
12326
12327 /* "applying" a token means performing it on the top elements on the integer
12328  * stack. For a unary operator it will only change the top element, but a
12329  * binary operator will pop two arguments and push a result */
12330 static int
12331 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12332 {
12333         v_n_t *numptr_m1;
12334         arith_t numptr_val, rez;
12335         int ret_arith_lookup_val;
12336
12337         /* There is no operator that can work without arguments */
12338         if (NUMPTR == numstack) goto err;
12339         numptr_m1 = NUMPTR - 1;
12340
12341         /* check operand is var with noninteger value */
12342         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12343         if (ret_arith_lookup_val)
12344                 return ret_arith_lookup_val;
12345
12346         rez = numptr_m1->val;
12347         if (op == TOK_UMINUS)
12348                 rez *= -1;
12349         else if (op == TOK_NOT)
12350                 rez = !rez;
12351         else if (op == TOK_BNOT)
12352                 rez = ~rez;
12353         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12354                 rez++;
12355         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12356                 rez--;
12357         else if (op != TOK_UPLUS) {
12358                 /* Binary operators */
12359
12360                 /* check and binary operators need two arguments */
12361                 if (numptr_m1 == numstack) goto err;
12362
12363                 /* ... and they pop one */
12364                 --NUMPTR;
12365                 numptr_val = rez;
12366                 if (op == TOK_CONDITIONAL) {
12367                         if (! numptr_m1->contidional_second_val_initialized) {
12368                                 /* protect $((expr1 ? expr2)) without ": expr" */
12369                                 goto err;
12370                         }
12371                         rez = numptr_m1->contidional_second_val;
12372                 } else if (numptr_m1->contidional_second_val_initialized) {
12373                         /* protect $((expr1 : expr2)) without "expr ? " */
12374                         goto err;
12375                 }
12376                 numptr_m1 = NUMPTR - 1;
12377                 if (op != TOK_ASSIGN) {
12378                         /* check operand is var with noninteger value for not '=' */
12379                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12380                         if (ret_arith_lookup_val)
12381                                 return ret_arith_lookup_val;
12382                 }
12383                 if (op == TOK_CONDITIONAL) {
12384                         numptr_m1->contidional_second_val = rez;
12385                 }
12386                 rez = numptr_m1->val;
12387                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12388                         rez |= numptr_val;
12389                 else if (op == TOK_OR)
12390                         rez = numptr_val || rez;
12391                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12392                         rez &= numptr_val;
12393                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12394                         rez ^= numptr_val;
12395                 else if (op == TOK_AND)
12396                         rez = rez && numptr_val;
12397                 else if (op == TOK_EQ)
12398                         rez = (rez == numptr_val);
12399                 else if (op == TOK_NE)
12400                         rez = (rez != numptr_val);
12401                 else if (op == TOK_GE)
12402                         rez = (rez >= numptr_val);
12403                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12404                         rez >>= numptr_val;
12405                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12406                         rez <<= numptr_val;
12407                 else if (op == TOK_GT)
12408                         rez = (rez > numptr_val);
12409                 else if (op == TOK_LT)
12410                         rez = (rez < numptr_val);
12411                 else if (op == TOK_LE)
12412                         rez = (rez <= numptr_val);
12413                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12414                         rez *= numptr_val;
12415                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12416                         rez += numptr_val;
12417                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12418                         rez -= numptr_val;
12419                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12420                         rez = numptr_val;
12421                 else if (op == TOK_CONDITIONAL_SEP) {
12422                         if (numptr_m1 == numstack) {
12423                                 /* protect $((expr : expr)) without "expr ? " */
12424                                 goto err;
12425                         }
12426                         numptr_m1->contidional_second_val_initialized = op;
12427                         numptr_m1->contidional_second_val = numptr_val;
12428                 } else if (op == TOK_CONDITIONAL) {
12429                         rez = rez ?
12430                                 numptr_val : numptr_m1->contidional_second_val;
12431                 } else if (op == TOK_EXPONENT) {
12432                         if (numptr_val < 0)
12433                                 return -3;      /* exponent less than 0 */
12434                         else {
12435                                 arith_t c = 1;
12436
12437                                 if (numptr_val)
12438                                         while (numptr_val--)
12439                                                 c *= rez;
12440                                 rez = c;
12441                         }
12442                 } else if (numptr_val==0)          /* zero divisor check */
12443                         return -2;
12444                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12445                         rez /= numptr_val;
12446                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12447                         rez %= numptr_val;
12448         }
12449         if (tok_have_assign(op)) {
12450                 char buf[sizeof(arith_t_type)*3 + 2];
12451
12452                 if (numptr_m1->var == NULL) {
12453                         /* Hmm, 1=2 ? */
12454                         goto err;
12455                 }
12456                 /* save to shell variable */
12457 #if ENABLE_ASH_MATH_SUPPORT_64
12458                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12459 #else
12460                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12461 #endif
12462                 setvar(numptr_m1->var, buf, 0);
12463                 /* after saving, make previous value for v++ or v-- */
12464                 if (op == TOK_POST_INC)
12465                         rez--;
12466                 else if (op == TOK_POST_DEC)
12467                         rez++;
12468         }
12469         numptr_m1->val = rez;
12470         /* protect geting var value, is number now */
12471         numptr_m1->var = NULL;
12472         return 0;
12473  err:
12474         return -1;
12475 }
12476
12477 /* longest must be first */
12478 static const char op_tokens[] ALIGN1 = {
12479         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12480         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12481         '<','<',    0, TOK_LSHIFT,
12482         '>','>',    0, TOK_RSHIFT,
12483         '|','|',    0, TOK_OR,
12484         '&','&',    0, TOK_AND,
12485         '!','=',    0, TOK_NE,
12486         '<','=',    0, TOK_LE,
12487         '>','=',    0, TOK_GE,
12488         '=','=',    0, TOK_EQ,
12489         '|','=',    0, TOK_OR_ASSIGN,
12490         '&','=',    0, TOK_AND_ASSIGN,
12491         '*','=',    0, TOK_MUL_ASSIGN,
12492         '/','=',    0, TOK_DIV_ASSIGN,
12493         '%','=',    0, TOK_REM_ASSIGN,
12494         '+','=',    0, TOK_PLUS_ASSIGN,
12495         '-','=',    0, TOK_MINUS_ASSIGN,
12496         '-','-',    0, TOK_POST_DEC,
12497         '^','=',    0, TOK_XOR_ASSIGN,
12498         '+','+',    0, TOK_POST_INC,
12499         '*','*',    0, TOK_EXPONENT,
12500         '!',        0, TOK_NOT,
12501         '<',        0, TOK_LT,
12502         '>',        0, TOK_GT,
12503         '=',        0, TOK_ASSIGN,
12504         '|',        0, TOK_BOR,
12505         '&',        0, TOK_BAND,
12506         '*',        0, TOK_MUL,
12507         '/',        0, TOK_DIV,
12508         '%',        0, TOK_REM,
12509         '+',        0, TOK_ADD,
12510         '-',        0, TOK_SUB,
12511         '^',        0, TOK_BXOR,
12512         /* uniq */
12513         '~',        0, TOK_BNOT,
12514         ',',        0, TOK_COMMA,
12515         '?',        0, TOK_CONDITIONAL,
12516         ':',        0, TOK_CONDITIONAL_SEP,
12517         ')',        0, TOK_RPAREN,
12518         '(',        0, TOK_LPAREN,
12519         0
12520 };
12521 /* ptr to ")" */
12522 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12523
12524 static arith_t
12525 arith(const char *expr, int *perrcode)
12526 {
12527         char arithval; /* Current character under analysis */
12528         operator lasttok, op;
12529         operator prec;
12530
12531         const char *p = endexpression;
12532         int errcode;
12533
12534         size_t datasizes = strlen(expr) + 2;
12535
12536         /* Stack of integers */
12537         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12538          * in any given correct or incorrect expression is left as an exercise to
12539          * the reader. */
12540         v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12541                                 *numstackptr = numstack;
12542         /* Stack of operator tokens */
12543         operator *stack = alloca((datasizes) * sizeof(operator)),
12544                                 *stackptr = stack;
12545
12546         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
12547         *perrcode = errcode = 0;
12548
12549         while (1) {
12550                 arithval = *expr;
12551                 if (arithval == 0) {
12552                         if (p == endexpression) {
12553                                 /* Null expression. */
12554                                 return 0;
12555                         }
12556
12557                         /* This is only reached after all tokens have been extracted from the
12558                          * input stream. If there are still tokens on the operator stack, they
12559                          * are to be applied in order. At the end, there should be a final
12560                          * result on the integer stack */
12561
12562                         if (expr != endexpression + 1) {
12563                                 /* If we haven't done so already, */
12564                                 /* append a closing right paren */
12565                                 expr = endexpression;
12566                                 /* and let the loop process it. */
12567                                 continue;
12568                         }
12569                         /* At this point, we're done with the expression. */
12570                         if (numstackptr != numstack+1) {
12571                                 /* ... but if there isn't, it's bad */
12572  err:
12573                                 return (*perrcode = -1);
12574                         }
12575                         if (numstack->var) {
12576                                 /* expression is $((var)) only, lookup now */
12577                                 errcode = arith_lookup_val(numstack);
12578                         }
12579  ret:
12580                         *perrcode = errcode;
12581                         return numstack->val;
12582                 }
12583
12584                 /* Continue processing the expression. */
12585                 if (arith_isspace(arithval)) {
12586                         /* Skip whitespace */
12587                         goto prologue;
12588                 }
12589                 p = endofname(expr);
12590                 if (p != expr) {
12591                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
12592
12593                         numstackptr->var = alloca(var_name_size);
12594                         safe_strncpy(numstackptr->var, expr, var_name_size);
12595                         expr = p;
12596  num:
12597                         numstackptr->contidional_second_val_initialized = 0;
12598                         numstackptr++;
12599                         lasttok = TOK_NUM;
12600                         continue;
12601                 }
12602                 if (isdigit(arithval)) {
12603                         numstackptr->var = NULL;
12604 #if ENABLE_ASH_MATH_SUPPORT_64
12605                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
12606 #else
12607                         numstackptr->val = strtol(expr, (char **) &expr, 0);
12608 #endif
12609                         goto num;
12610                 }
12611                 for (p = op_tokens; ; p++) {
12612                         const char *o;
12613
12614                         if (*p == 0) {
12615                                 /* strange operator not found */
12616                                 goto err;
12617                         }
12618                         for (o = expr; *p && *o == *p; p++)
12619                                 o++;
12620                         if (! *p) {
12621                                 /* found */
12622                                 expr = o - 1;
12623                                 break;
12624                         }
12625                         /* skip tail uncompared token */
12626                         while (*p)
12627                                 p++;
12628                         /* skip zero delim */
12629                         p++;
12630                 }
12631                 op = p[1];
12632
12633                 /* post grammar: a++ reduce to num */
12634                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12635                         lasttok = TOK_NUM;
12636
12637                 /* Plus and minus are binary (not unary) _only_ if the last
12638                  * token was as number, or a right paren (which pretends to be
12639                  * a number, since it evaluates to one). Think about it.
12640                  * It makes sense. */
12641                 if (lasttok != TOK_NUM) {
12642                         switch (op) {
12643                         case TOK_ADD:
12644                                 op = TOK_UPLUS;
12645                                 break;
12646                         case TOK_SUB:
12647                                 op = TOK_UMINUS;
12648                                 break;
12649                         case TOK_POST_INC:
12650                                 op = TOK_PRE_INC;
12651                                 break;
12652                         case TOK_POST_DEC:
12653                                 op = TOK_PRE_DEC;
12654                                 break;
12655                         }
12656                 }
12657                 /* We don't want a unary operator to cause recursive descent on the
12658                  * stack, because there can be many in a row and it could cause an
12659                  * operator to be evaluated before its argument is pushed onto the
12660                  * integer stack. */
12661                 /* But for binary operators, "apply" everything on the operator
12662                  * stack until we find an operator with a lesser priority than the
12663                  * one we have just extracted. */
12664                 /* Left paren is given the lowest priority so it will never be
12665                  * "applied" in this way.
12666                  * if associativity is right and priority eq, applied also skip
12667                  */
12668                 prec = PREC(op);
12669                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12670                         /* not left paren or unary */
12671                         if (lasttok != TOK_NUM) {
12672                                 /* binary op must be preceded by a num */
12673                                 goto err;
12674                         }
12675                         while (stackptr != stack) {
12676                                 if (op == TOK_RPAREN) {
12677                                         /* The algorithm employed here is simple: while we don't
12678                                          * hit an open paren nor the bottom of the stack, pop
12679                                          * tokens and apply them */
12680                                         if (stackptr[-1] == TOK_LPAREN) {
12681                                                 --stackptr;
12682                                                 /* Any operator directly after a */
12683                                                 lasttok = TOK_NUM;
12684                                                 /* close paren should consider itself binary */
12685                                                 goto prologue;
12686                                         }
12687                                 } else {
12688                                         operator prev_prec = PREC(stackptr[-1]);
12689
12690                                         convert_prec_is_assing(prec);
12691                                         convert_prec_is_assing(prev_prec);
12692                                         if (prev_prec < prec)
12693                                                 break;
12694                                         /* check right assoc */
12695                                         if (prev_prec == prec && is_right_associativity(prec))
12696                                                 break;
12697                                 }
12698                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12699                                 if (errcode) goto ret;
12700                         }
12701                         if (op == TOK_RPAREN) {
12702                                 goto err;
12703                         }
12704                 }
12705
12706                 /* Push this operator to the stack and remember it. */
12707                 *stackptr++ = lasttok = op;
12708  prologue:
12709                 ++expr;
12710         } /* while */
12711 }
12712 #endif /* ASH_MATH_SUPPORT */
12713
12714
12715 /* ============ main() and helpers */
12716
12717 /*
12718  * Called to exit the shell.
12719  */
12720 static void exitshell(void) ATTRIBUTE_NORETURN;
12721 static void
12722 exitshell(void)
12723 {
12724         struct jmploc loc;
12725         char *p;
12726         int status;
12727
12728         status = exitstatus;
12729         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12730         if (setjmp(loc.loc)) {
12731                 if (exception == EXEXIT)
12732 /* dash bug: it just does _exit(exitstatus) here
12733  * but we have to do setjobctl(0) first!
12734  * (bug is still not fixed in dash-0.5.3 - if you run dash
12735  * under Midnight Commander, on exit from dash MC is backgrounded) */
12736                         status = exitstatus;
12737                 goto out;
12738         }
12739         exception_handler = &loc;
12740         p = trap[0];
12741         if (p) {
12742                 trap[0] = NULL;
12743                 evalstring(p, 0);
12744         }
12745         flush_stdout_stderr();
12746  out:
12747         setjobctl(0);
12748         _exit(status);
12749         /* NOTREACHED */
12750 }
12751
12752 static void
12753 init(void)
12754 {
12755         /* from input.c: */
12756         basepf.nextc = basepf.buf = basebuf;
12757
12758         /* from trap.c: */
12759         signal(SIGCHLD, SIG_DFL);
12760
12761         /* from var.c: */
12762         {
12763                 char **envp;
12764                 char ppid[sizeof(int)*3 + 1];
12765                 const char *p;
12766                 struct stat st1, st2;
12767
12768                 initvar();
12769                 for (envp = environ; envp && *envp; envp++) {
12770                         if (strchr(*envp, '=')) {
12771                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12772                         }
12773                 }
12774
12775                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12776                 setvar("PPID", ppid, 0);
12777
12778                 p = lookupvar("PWD");
12779                 if (p)
12780                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12781                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12782                                 p = '\0';
12783                 setpwd(p, 0);
12784         }
12785 }
12786
12787 /*
12788  * Process the shell command line arguments.
12789  */
12790 static void
12791 procargs(int argc, char **argv)
12792 {
12793         int i;
12794         const char *xminusc;
12795         char **xargv;
12796
12797         xargv = argv;
12798         arg0 = xargv[0];
12799         if (argc > 0)
12800                 xargv++;
12801         for (i = 0; i < NOPTS; i++)
12802                 optlist[i] = 2;
12803         argptr = xargv;
12804         if (options(1)) {
12805                 /* it already printed err message */
12806                 raise_exception(EXERROR);
12807         }
12808         xargv = argptr;
12809         xminusc = minusc;
12810         if (*xargv == NULL) {
12811                 if (xminusc)
12812                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12813                 sflag = 1;
12814         }
12815         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12816                 iflag = 1;
12817         if (mflag == 2)
12818                 mflag = iflag;
12819         for (i = 0; i < NOPTS; i++)
12820                 if (optlist[i] == 2)
12821                         optlist[i] = 0;
12822 #if DEBUG == 2
12823         debug = 1;
12824 #endif
12825         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12826         if (xminusc) {
12827                 minusc = *xargv++;
12828                 if (*xargv)
12829                         goto setarg0;
12830         } else if (!sflag) {
12831                 setinputfile(*xargv, 0);
12832  setarg0:
12833                 arg0 = *xargv++;
12834                 commandname = arg0;
12835         }
12836
12837         shellparam.p = xargv;
12838 #if ENABLE_ASH_GETOPTS
12839         shellparam.optind = 1;
12840         shellparam.optoff = -1;
12841 #endif
12842         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
12843         while (*xargv) {
12844                 shellparam.nparam++;
12845                 xargv++;
12846         }
12847         optschanged();
12848 }
12849
12850 /*
12851  * Read /etc/profile or .profile.
12852  */
12853 static void
12854 read_profile(const char *name)
12855 {
12856         int skip;
12857
12858         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12859                 return;
12860         skip = cmdloop(0);
12861         popfile();
12862         if (skip)
12863                 exitshell();
12864 }
12865
12866 /*
12867  * This routine is called when an error or an interrupt occurs in an
12868  * interactive shell and control is returned to the main command loop.
12869  */
12870 static void
12871 reset(void)
12872 {
12873         /* from eval.c: */
12874         evalskip = 0;
12875         loopnest = 0;
12876         /* from input.c: */
12877         parselleft = parsenleft = 0;      /* clear input buffer */
12878         popallfiles();
12879         /* from parser.c: */
12880         tokpushback = 0;
12881         checkkwd = 0;
12882         /* from redir.c: */
12883         clearredir(0);
12884 }
12885
12886 #if PROFILE
12887 static short profile_buf[16384];
12888 extern int etext();
12889 #endif
12890
12891 /*
12892  * Main routine.  We initialize things, parse the arguments, execute
12893  * profiles if we're a login shell, and then call cmdloop to execute
12894  * commands.  The setjmp call sets up the location to jump to when an
12895  * exception occurs.  When an exception occurs the variable "state"
12896  * is used to figure out how far we had gotten.
12897  */
12898 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
12899 int ash_main(int argc, char **argv)
12900 {
12901         char *shinit;
12902         volatile int state;
12903         struct jmploc jmploc;
12904         struct stackmark smark;
12905
12906         /* Initialize global data */
12907         INIT_G_misc();
12908         INIT_G_memstack();
12909         INIT_G_var();
12910 #if ENABLE_ASH_ALIAS
12911         INIT_G_alias();
12912 #endif
12913         INIT_G_cmdtable();
12914
12915 #if PROFILE
12916         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12917 #endif
12918
12919 #if ENABLE_FEATURE_EDITING
12920         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12921 #endif
12922         state = 0;
12923         if (setjmp(jmploc.loc)) {
12924                 int e;
12925                 int s;
12926
12927                 reset();
12928
12929                 e = exception;
12930                 if (e == EXERROR)
12931                         exitstatus = 2;
12932                 s = state;
12933                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12934                         exitshell();
12935
12936                 if (e == EXINT) {
12937                         outcslow('\n', stderr);
12938                 }
12939                 popstackmark(&smark);
12940                 FORCE_INT_ON; /* enable interrupts */
12941                 if (s == 1)
12942                         goto state1;
12943                 if (s == 2)
12944                         goto state2;
12945                 if (s == 3)
12946                         goto state3;
12947                 goto state4;
12948         }
12949         exception_handler = &jmploc;
12950 #if DEBUG
12951         opentrace();
12952         trace_puts("Shell args: ");
12953         trace_puts_args(argv);
12954 #endif
12955         rootpid = getpid();
12956
12957 #if ENABLE_ASH_RANDOM_SUPPORT
12958         rseed = rootpid + time(NULL);
12959 #endif
12960         init();
12961         setstackmark(&smark);
12962         procargs(argc, argv);
12963 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12964         if (iflag) {
12965                 const char *hp = lookupvar("HISTFILE");
12966
12967                 if (hp == NULL) {
12968                         hp = lookupvar("HOME");
12969                         if (hp != NULL) {
12970                                 char *defhp = concat_path_file(hp, ".ash_history");
12971                                 setvar("HISTFILE", defhp, 0);
12972                                 free(defhp);
12973                         }
12974                 }
12975         }
12976 #endif
12977         if (argv[0] && argv[0][0] == '-')
12978                 isloginsh = 1;
12979         if (isloginsh) {
12980                 state = 1;
12981                 read_profile("/etc/profile");
12982  state1:
12983                 state = 2;
12984                 read_profile(".profile");
12985         }
12986  state2:
12987         state = 3;
12988         if (
12989 #ifndef linux
12990          getuid() == geteuid() && getgid() == getegid() &&
12991 #endif
12992          iflag
12993         ) {
12994                 shinit = lookupvar("ENV");
12995                 if (shinit != NULL && *shinit != '\0') {
12996                         read_profile(shinit);
12997                 }
12998         }
12999  state3:
13000         state = 4;
13001         if (minusc)
13002                 evalstring(minusc, 0);
13003
13004         if (sflag || minusc == NULL) {
13005 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13006                 if ( iflag ) {
13007                         const char *hp = lookupvar("HISTFILE");
13008
13009                         if (hp != NULL)
13010                                 line_input_state->hist_file = hp;
13011                 }
13012 #endif
13013  state4: /* XXX ??? - why isn't this before the "if" statement */
13014                 cmdloop(1);
13015         }
13016 #if PROFILE
13017         monitor(0);
13018 #endif
13019 #ifdef GPROF
13020         {
13021                 extern void _mcleanup(void);
13022                 _mcleanup();
13023         }
13024 #endif
13025         exitshell();
13026         /* NOTREACHED */
13027 }
13028
13029 #if DEBUG
13030 const char *applet_name = "debug stuff usage";
13031 int main(int argc, char **argv)
13032 {
13033         return ash_main(argc, argv);
13034 }
13035 #endif
13036
13037
13038 /*-
13039  * Copyright (c) 1989, 1991, 1993, 1994
13040  *      The Regents of the University of California.  All rights reserved.
13041  *
13042  * This code is derived from software contributed to Berkeley by
13043  * Kenneth Almquist.
13044  *
13045  * Redistribution and use in source and binary forms, with or without
13046  * modification, are permitted provided that the following conditions
13047  * are met:
13048  * 1. Redistributions of source code must retain the above copyright
13049  *    notice, this list of conditions and the following disclaimer.
13050  * 2. Redistributions in binary form must reproduce the above copyright
13051  *    notice, this list of conditions and the following disclaimer in the
13052  *    documentation and/or other materials provided with the distribution.
13053  * 3. Neither the name of the University nor the names of its contributors
13054  *    may be used to endorse or promote products derived from this software
13055  *    without specific prior written permission.
13056  *
13057  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13058  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13059  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13060  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13061  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13062  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13063  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13064  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13065  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13066  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13067  * SUCH DAMAGE.
13068  */