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