d63acc2c84b5cdcd33a9a958bbacbf07ab09b6c4
[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]; /* offset by 1: "signal" 0 is meaningless */
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) /* remembering 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 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4905 static int is_hidden_fd(struct redirtab *rp, int fd)
4906 {
4907         int i;
4908         struct parsefile *pf;
4909
4910         if (fd == -1)
4911                 return 0;
4912         pf = g_parsefile;
4913         while (pf) {
4914                 if (fd == pf->fd) {
4915                         return 1;
4916                 }
4917                 pf = pf->prev;
4918         }
4919         if (!rp)
4920                 return 0;
4921         fd |= COPYFD_RESTORE;
4922         for (i = 0; i < rp->pair_count; i++) {
4923                 if (rp->two_fd[i].copy == fd) {
4924                         return 1;
4925                 }
4926         }
4927         return 0;
4928 }
4929
4930 /*
4931  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
4932  * old file descriptors are stashed away so that the redirection can be
4933  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
4934  * standard output, and the standard error if it becomes a duplicate of
4935  * stdout, is saved in memory.
4936  */
4937 /* flags passed to redirect */
4938 #define REDIR_PUSH    01        /* save previous values of file descriptors */
4939 #define REDIR_SAVEFD2 03        /* set preverrout */
4940 static void
4941 redirect(union node *redir, int flags)
4942 {
4943         struct redirtab *sv;
4944         int sv_pos;
4945         int i;
4946         int fd;
4947         int newfd;
4948         int copied_fd2 = -1;
4949
4950         g_nullredirs++;
4951         if (!redir) {
4952                 return;
4953         }
4954
4955         sv = NULL;
4956         sv_pos = 0;
4957         INT_OFF;
4958         if (flags & REDIR_PUSH) {
4959                 union node *tmp = redir;
4960                 do {
4961                         sv_pos++;
4962                         tmp = tmp->nfile.next;
4963                 } while (tmp);
4964                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
4965                 sv->next = redirlist;
4966                 sv->pair_count = sv_pos;
4967                 redirlist = sv;
4968                 sv->nullredirs = g_nullredirs - 1;
4969                 g_nullredirs = 0;
4970                 while (sv_pos > 0) {
4971                         sv_pos--;
4972                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
4973                 }
4974         }
4975
4976         do {
4977                 fd = redir->nfile.fd;
4978                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4979                         int right_fd = redir->ndup.dupfd;
4980                         /* redirect from/to same file descriptor? */
4981                         if (right_fd == fd)
4982                                 continue;
4983                         /* echo >&10 and 10 is a fd opened to the sh script? */
4984                         if (is_hidden_fd(sv, right_fd)) {
4985                                 errno = EBADF; /* as if it is closed */
4986                                 ash_msg_and_raise_error("%d: %m", right_fd);
4987                         }
4988                         newfd = -1;
4989                 } else {
4990                         newfd = openredirect(redir); /* always >= 0 */
4991                         if (fd == newfd) {
4992                                 /* Descriptor wasn't open before redirect.
4993                                  * Mark it for close in the future */
4994                                 if (need_to_remember(sv, fd)) {
4995                                         goto remember_to_close;
4996                                 }
4997                                 continue;
4998                         }
4999                 }
5000                 if (need_to_remember(sv, fd)) {
5001                         /* Copy old descriptor */
5002                         i = fcntl(fd, F_DUPFD, 10);
5003 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5004  * are closed in popredir() in the child, preventing them from leaking
5005  * into child. (popredir() also cleans up the mess in case of failures)
5006  */
5007                         if (i == -1) {
5008                                 i = errno;
5009                                 if (i != EBADF) {
5010                                         /* Strange error (e.g. "too many files" EMFILE?) */
5011                                         if (newfd >= 0)
5012                                                 close(newfd);
5013                                         errno = i;
5014                                         ash_msg_and_raise_error("%d: %m", fd);
5015                                         /* NOTREACHED */
5016                                 }
5017                                 /* EBADF: it is not open - good, remember to close it */
5018  remember_to_close:
5019                                 i = CLOSED;
5020                         } else { /* fd is open, save its copy */
5021                                 /* "exec fd>&-" should not close fds
5022                                  * which point to script file(s).
5023                                  * Force them to be restored afterwards */
5024                                 if (is_hidden_fd(sv, fd))
5025                                         i |= COPYFD_RESTORE;
5026                         }
5027                         if (fd == 2)
5028                                 copied_fd2 = i;
5029                         sv->two_fd[sv_pos].orig = fd;
5030                         sv->two_fd[sv_pos].copy = i;
5031                         sv_pos++;
5032                 }
5033                 if (newfd < 0) {
5034                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5035                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5036                                 close(fd);
5037                         } else {
5038                                 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5039                         }
5040                 } else if (fd != newfd) { /* move newfd to fd */
5041                         copyfd(newfd, fd | COPYFD_EXACT);
5042                         close(newfd);
5043                 }
5044         } while ((redir = redir->nfile.next) != NULL);
5045
5046         INT_ON;
5047         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5048                 preverrout_fd = copied_fd2;
5049 }
5050
5051 /*
5052  * Undo the effects of the last redirection.
5053  */
5054 static void
5055 popredir(int drop, int restore)
5056 {
5057         struct redirtab *rp;
5058         int i;
5059
5060         if (--g_nullredirs >= 0)
5061                 return;
5062         INT_OFF;
5063         rp = redirlist;
5064         for (i = 0; i < rp->pair_count; i++) {
5065                 int fd = rp->two_fd[i].orig;
5066                 int copy = rp->two_fd[i].copy;
5067                 if (copy == CLOSED) {
5068                         if (!drop)
5069                                 close(fd);
5070                         continue;
5071                 }
5072                 if (copy != EMPTY) {
5073                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5074                                 copy &= ~COPYFD_RESTORE;
5075                                 /*close(fd);*/
5076                                 copyfd(copy, fd | COPYFD_EXACT);
5077                         }
5078                         close(copy);
5079                 }
5080         }
5081         redirlist = rp->next;
5082         g_nullredirs = rp->nullredirs;
5083         free(rp);
5084         INT_ON;
5085 }
5086
5087 /*
5088  * Undo all redirections.  Called on error or interrupt.
5089  */
5090
5091 /*
5092  * Discard all saved file descriptors.
5093  */
5094 static void
5095 clearredir(int drop)
5096 {
5097         for (;;) {
5098                 g_nullredirs = 0;
5099                 if (!redirlist)
5100                         break;
5101                 popredir(drop, /*restore:*/ 0);
5102         }
5103 }
5104
5105 static int
5106 redirectsafe(union node *redir, int flags)
5107 {
5108         int err;
5109         volatile int saveint;
5110         struct jmploc *volatile savehandler = exception_handler;
5111         struct jmploc jmploc;
5112
5113         SAVE_INT(saveint);
5114         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5115         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5116         if (!err) {
5117                 exception_handler = &jmploc;
5118                 redirect(redir, flags);
5119         }
5120         exception_handler = savehandler;
5121         if (err && exception != EXERROR)
5122                 longjmp(exception_handler->loc, 1);
5123         RESTORE_INT(saveint);
5124         return err;
5125 }
5126
5127
5128 /* ============ Routines to expand arguments to commands
5129  *
5130  * We have to deal with backquotes, shell variables, and file metacharacters.
5131  */
5132
5133 #if ENABLE_ASH_MATH_SUPPORT_64
5134 typedef int64_t arith_t;
5135 #define arith_t_type long long
5136 #else
5137 typedef long arith_t;
5138 #define arith_t_type long
5139 #endif
5140
5141 #if ENABLE_ASH_MATH_SUPPORT
5142 static arith_t dash_arith(const char *);
5143 static arith_t arith(const char *expr, int *perrcode);
5144 #endif
5145
5146 /*
5147  * expandarg flags
5148  */
5149 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5150 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5151 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5152 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5153 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5154 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
5155 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5156 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5157 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
5158 /*
5159  * _rmescape() flags
5160  */
5161 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5162 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5163 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
5164 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5165 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5166
5167 /*
5168  * Structure specifying which parts of the string should be searched
5169  * for IFS characters.
5170  */
5171 struct ifsregion {
5172         struct ifsregion *next; /* next region in list */
5173         int begoff;             /* offset of start of region */
5174         int endoff;             /* offset of end of region */
5175         int nulonly;            /* search for nul bytes only */
5176 };
5177
5178 struct arglist {
5179         struct strlist *list;
5180         struct strlist **lastp;
5181 };
5182
5183 /* output of current string */
5184 static char *expdest;
5185 /* list of back quote expressions */
5186 static struct nodelist *argbackq;
5187 /* first struct in list of ifs regions */
5188 static struct ifsregion ifsfirst;
5189 /* last struct in list */
5190 static struct ifsregion *ifslastp;
5191 /* holds expanded arg list */
5192 static struct arglist exparg;
5193
5194 /*
5195  * Our own itoa().
5196  */
5197 static int
5198 cvtnum(arith_t num)
5199 {
5200         int len;
5201
5202         expdest = makestrspace(32, expdest);
5203 #if ENABLE_ASH_MATH_SUPPORT_64
5204         len = fmtstr(expdest, 32, "%lld", (long long) num);
5205 #else
5206         len = fmtstr(expdest, 32, "%ld", num);
5207 #endif
5208         STADJUST(len, expdest);
5209         return len;
5210 }
5211
5212 static size_t
5213 esclen(const char *start, const char *p)
5214 {
5215         size_t esc = 0;
5216
5217         while (p > start && *--p == CTLESC) {
5218                 esc++;
5219         }
5220         return esc;
5221 }
5222
5223 /*
5224  * Remove any CTLESC characters from a string.
5225  */
5226 static char *
5227 _rmescapes(char *str, int flag)
5228 {
5229         static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5230
5231         char *p, *q, *r;
5232         unsigned inquotes;
5233         int notescaped;
5234         int globbing;
5235
5236         p = strpbrk(str, qchars);
5237         if (!p) {
5238                 return str;
5239         }
5240         q = p;
5241         r = str;
5242         if (flag & RMESCAPE_ALLOC) {
5243                 size_t len = p - str;
5244                 size_t fulllen = len + strlen(p) + 1;
5245
5246                 if (flag & RMESCAPE_GROW) {
5247                         r = makestrspace(fulllen, expdest);
5248                 } else if (flag & RMESCAPE_HEAP) {
5249                         r = ckmalloc(fulllen);
5250                 } else {
5251                         r = stalloc(fulllen);
5252                 }
5253                 q = r;
5254                 if (len > 0) {
5255                         q = (char *)memcpy(q, str, len) + len;
5256                 }
5257         }
5258         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5259         globbing = flag & RMESCAPE_GLOB;
5260         notescaped = globbing;
5261         while (*p) {
5262                 if (*p == CTLQUOTEMARK) {
5263                         inquotes = ~inquotes;
5264                         p++;
5265                         notescaped = globbing;
5266                         continue;
5267                 }
5268                 if (*p == '\\') {
5269                         /* naked back slash */
5270                         notescaped = 0;
5271                         goto copy;
5272                 }
5273                 if (*p == CTLESC) {
5274                         p++;
5275                         if (notescaped && inquotes && *p != '/') {
5276                                 *q++ = '\\';
5277                         }
5278                 }
5279                 notescaped = globbing;
5280  copy:
5281                 *q++ = *p++;
5282         }
5283         *q = '\0';
5284         if (flag & RMESCAPE_GROW) {
5285                 expdest = r;
5286                 STADJUST(q - r + 1, expdest);
5287         }
5288         return r;
5289 }
5290 #define rmescapes(p) _rmescapes((p), 0)
5291
5292 #define pmatch(a, b) !fnmatch((a), (b), 0)
5293
5294 /*
5295  * Prepare a pattern for a expmeta (internal glob(3)) call.
5296  *
5297  * Returns an stalloced string.
5298  */
5299 static char *
5300 preglob(const char *pattern, int quoted, int flag)
5301 {
5302         flag |= RMESCAPE_GLOB;
5303         if (quoted) {
5304                 flag |= RMESCAPE_QUOTED;
5305         }
5306         return _rmescapes((char *)pattern, flag);
5307 }
5308
5309 /*
5310  * Put a string on the stack.
5311  */
5312 static void
5313 memtodest(const char *p, size_t len, int syntax, int quotes)
5314 {
5315         char *q = expdest;
5316
5317         q = makestrspace(len * 2, q);
5318
5319         while (len--) {
5320                 int c = signed_char2int(*p++);
5321                 if (!c)
5322                         continue;
5323                 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5324                         USTPUTC(CTLESC, q);
5325                 USTPUTC(c, q);
5326         }
5327
5328         expdest = q;
5329 }
5330
5331 static void
5332 strtodest(const char *p, int syntax, int quotes)
5333 {
5334         memtodest(p, strlen(p), syntax, quotes);
5335 }
5336
5337 /*
5338  * Record the fact that we have to scan this region of the
5339  * string for IFS characters.
5340  */
5341 static void
5342 recordregion(int start, int end, int nulonly)
5343 {
5344         struct ifsregion *ifsp;
5345
5346         if (ifslastp == NULL) {
5347                 ifsp = &ifsfirst;
5348         } else {
5349                 INT_OFF;
5350                 ifsp = ckzalloc(sizeof(*ifsp));
5351                 /*ifsp->next = NULL; - ckzalloc did it */
5352                 ifslastp->next = ifsp;
5353                 INT_ON;
5354         }
5355         ifslastp = ifsp;
5356         ifslastp->begoff = start;
5357         ifslastp->endoff = end;
5358         ifslastp->nulonly = nulonly;
5359 }
5360
5361 static void
5362 removerecordregions(int endoff)
5363 {
5364         if (ifslastp == NULL)
5365                 return;
5366
5367         if (ifsfirst.endoff > endoff) {
5368                 while (ifsfirst.next != NULL) {
5369                         struct ifsregion *ifsp;
5370                         INT_OFF;
5371                         ifsp = ifsfirst.next->next;
5372                         free(ifsfirst.next);
5373                         ifsfirst.next = ifsp;
5374                         INT_ON;
5375                 }
5376                 if (ifsfirst.begoff > endoff)
5377                         ifslastp = NULL;
5378                 else {
5379                         ifslastp = &ifsfirst;
5380                         ifsfirst.endoff = endoff;
5381                 }
5382                 return;
5383         }
5384
5385         ifslastp = &ifsfirst;
5386         while (ifslastp->next && ifslastp->next->begoff < endoff)
5387                 ifslastp=ifslastp->next;
5388         while (ifslastp->next != NULL) {
5389                 struct ifsregion *ifsp;
5390                 INT_OFF;
5391                 ifsp = ifslastp->next->next;
5392                 free(ifslastp->next);
5393                 ifslastp->next = ifsp;
5394                 INT_ON;
5395         }
5396         if (ifslastp->endoff > endoff)
5397                 ifslastp->endoff = endoff;
5398 }
5399
5400 static char *
5401 exptilde(char *startp, char *p, int flag)
5402 {
5403         char c;
5404         char *name;
5405         struct passwd *pw;
5406         const char *home;
5407         int quotes = flag & (EXP_FULL | EXP_CASE);
5408         int startloc;
5409
5410         name = p + 1;
5411
5412         while ((c = *++p) != '\0') {
5413                 switch (c) {
5414                 case CTLESC:
5415                         return startp;
5416                 case CTLQUOTEMARK:
5417                         return startp;
5418                 case ':':
5419                         if (flag & EXP_VARTILDE)
5420                                 goto done;
5421                         break;
5422                 case '/':
5423                 case CTLENDVAR:
5424                         goto done;
5425                 }
5426         }
5427  done:
5428         *p = '\0';
5429         if (*name == '\0') {
5430                 home = lookupvar(homestr);
5431         } else {
5432                 pw = getpwnam(name);
5433                 if (pw == NULL)
5434                         goto lose;
5435                 home = pw->pw_dir;
5436         }
5437         if (!home || !*home)
5438                 goto lose;
5439         *p = c;
5440         startloc = expdest - (char *)stackblock();
5441         strtodest(home, SQSYNTAX, quotes);
5442         recordregion(startloc, expdest - (char *)stackblock(), 0);
5443         return p;
5444  lose:
5445         *p = c;
5446         return startp;
5447 }
5448
5449 /*
5450  * Execute a command inside back quotes.  If it's a builtin command, we
5451  * want to save its output in a block obtained from malloc.  Otherwise
5452  * we fork off a subprocess and get the output of the command via a pipe.
5453  * Should be called with interrupts off.
5454  */
5455 struct backcmd {                /* result of evalbackcmd */
5456         int fd;                 /* file descriptor to read from */
5457         int nleft;              /* number of chars in buffer */
5458         char *buf;              /* buffer */
5459         struct job *jp;         /* job structure for command */
5460 };
5461
5462 /* These forward decls are needed to use "eval" code for backticks handling: */
5463 static uint8_t back_exitstatus; /* exit status of backquoted command */
5464 #define EV_EXIT 01              /* exit after evaluating tree */
5465 static void evaltree(union node *, int);
5466
5467 static void
5468 evalbackcmd(union node *n, struct backcmd *result)
5469 {
5470         int saveherefd;
5471
5472         result->fd = -1;
5473         result->buf = NULL;
5474         result->nleft = 0;
5475         result->jp = NULL;
5476         if (n == NULL) {
5477                 goto out;
5478         }
5479
5480         saveherefd = herefd;
5481         herefd = -1;
5482
5483         {
5484                 int pip[2];
5485                 struct job *jp;
5486
5487                 if (pipe(pip) < 0)
5488                         ash_msg_and_raise_error("pipe call failed");
5489                 jp = makejob(/*n,*/ 1);
5490                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5491                         FORCE_INT_ON;
5492                         close(pip[0]);
5493                         if (pip[1] != 1) {
5494                                 /*close(1);*/
5495                                 copyfd(pip[1], 1 | COPYFD_EXACT);
5496                                 close(pip[1]);
5497                         }
5498                         eflag = 0;
5499                         evaltree(n, EV_EXIT); /* actually evaltreenr... */
5500                         /* NOTREACHED */
5501                 }
5502                 close(pip[1]);
5503                 result->fd = pip[0];
5504                 result->jp = jp;
5505         }
5506         herefd = saveherefd;
5507  out:
5508         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5509                 result->fd, result->buf, result->nleft, result->jp));
5510 }
5511
5512 /*
5513  * Expand stuff in backwards quotes.
5514  */
5515 static void
5516 expbackq(union node *cmd, int quoted, int quotes)
5517 {
5518         struct backcmd in;
5519         int i;
5520         char buf[128];
5521         char *p;
5522         char *dest;
5523         int startloc;
5524         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5525         struct stackmark smark;
5526
5527         INT_OFF;
5528         setstackmark(&smark);
5529         dest = expdest;
5530         startloc = dest - (char *)stackblock();
5531         grabstackstr(dest);
5532         evalbackcmd(cmd, &in);
5533         popstackmark(&smark);
5534
5535         p = in.buf;
5536         i = in.nleft;
5537         if (i == 0)
5538                 goto read;
5539         for (;;) {
5540                 memtodest(p, i, syntax, quotes);
5541  read:
5542                 if (in.fd < 0)
5543                         break;
5544                 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5545                 TRACE(("expbackq: read returns %d\n", i));
5546                 if (i <= 0)
5547                         break;
5548                 p = buf;
5549         }
5550
5551         free(in.buf);
5552         if (in.fd >= 0) {
5553                 close(in.fd);
5554                 back_exitstatus = waitforjob(in.jp);
5555         }
5556         INT_ON;
5557
5558         /* Eat all trailing newlines */
5559         dest = expdest;
5560         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5561                 STUNPUTC(dest);
5562         expdest = dest;
5563
5564         if (quoted == 0)
5565                 recordregion(startloc, dest - (char *)stackblock(), 0);
5566         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5567                 (dest - (char *)stackblock()) - startloc,
5568                 (dest - (char *)stackblock()) - startloc,
5569                 stackblock() + startloc));
5570 }
5571
5572 #if ENABLE_ASH_MATH_SUPPORT
5573 /*
5574  * Expand arithmetic expression.  Backup to start of expression,
5575  * evaluate, place result in (backed up) result, adjust string position.
5576  */
5577 static void
5578 expari(int quotes)
5579 {
5580         char *p, *start;
5581         int begoff;
5582         int flag;
5583         int len;
5584
5585         /*      ifsfree(); */
5586
5587         /*
5588          * This routine is slightly over-complicated for
5589          * efficiency.  Next we scan backwards looking for the
5590          * start of arithmetic.
5591          */
5592         start = stackblock();
5593         p = expdest - 1;
5594         *p = '\0';
5595         p--;
5596         do {
5597                 int esc;
5598
5599                 while (*p != CTLARI) {
5600                         p--;
5601 #if DEBUG
5602                         if (p < start) {
5603                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5604                         }
5605 #endif
5606                 }
5607
5608                 esc = esclen(start, p);
5609                 if (!(esc % 2)) {
5610                         break;
5611                 }
5612
5613                 p -= esc + 1;
5614         } while (1);
5615
5616         begoff = p - start;
5617
5618         removerecordregions(begoff);
5619
5620         flag = p[1];
5621
5622         expdest = p;
5623
5624         if (quotes)
5625                 rmescapes(p + 2);
5626
5627         len = cvtnum(dash_arith(p + 2));
5628
5629         if (flag != '"')
5630                 recordregion(begoff, begoff + len, 0);
5631 }
5632 #endif
5633
5634 /* argstr needs it */
5635 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5636
5637 /*
5638  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
5639  * characters to allow for further processing.  Otherwise treat
5640  * $@ like $* since no splitting will be performed.
5641  *
5642  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5643  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5644  * for correct expansion of "B=$A" word.
5645  */
5646 static void
5647 argstr(char *p, int flag, struct strlist *var_str_list)
5648 {
5649         static const char spclchars[] ALIGN1 = {
5650                 '=',
5651                 ':',
5652                 CTLQUOTEMARK,
5653                 CTLENDVAR,
5654                 CTLESC,
5655                 CTLVAR,
5656                 CTLBACKQ,
5657                 CTLBACKQ | CTLQUOTE,
5658 #if ENABLE_ASH_MATH_SUPPORT
5659                 CTLENDARI,
5660 #endif
5661                 0
5662         };
5663         const char *reject = spclchars;
5664         int c;
5665         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
5666         int breakall = flag & EXP_WORD;
5667         int inquotes;
5668         size_t length;
5669         int startloc;
5670
5671         if (!(flag & EXP_VARTILDE)) {
5672                 reject += 2;
5673         } else if (flag & EXP_VARTILDE2) {
5674                 reject++;
5675         }
5676         inquotes = 0;
5677         length = 0;
5678         if (flag & EXP_TILDE) {
5679                 char *q;
5680
5681                 flag &= ~EXP_TILDE;
5682  tilde:
5683                 q = p;
5684                 if (*q == CTLESC && (flag & EXP_QWORD))
5685                         q++;
5686                 if (*q == '~')
5687                         p = exptilde(p, q, flag);
5688         }
5689  start:
5690         startloc = expdest - (char *)stackblock();
5691         for (;;) {
5692                 length += strcspn(p + length, reject);
5693                 c = p[length];
5694                 if (c && (!(c & 0x80)
5695 #if ENABLE_ASH_MATH_SUPPORT
5696                                         || c == CTLENDARI
5697 #endif
5698                    )) {
5699                         /* c == '=' || c == ':' || c == CTLENDARI */
5700                         length++;
5701                 }
5702                 if (length > 0) {
5703                         int newloc;
5704                         expdest = stack_nputstr(p, length, expdest);
5705                         newloc = expdest - (char *)stackblock();
5706                         if (breakall && !inquotes && newloc > startloc) {
5707                                 recordregion(startloc, newloc, 0);
5708                         }
5709                         startloc = newloc;
5710                 }
5711                 p += length + 1;
5712                 length = 0;
5713
5714                 switch (c) {
5715                 case '\0':
5716                         goto breakloop;
5717                 case '=':
5718                         if (flag & EXP_VARTILDE2) {
5719                                 p--;
5720                                 continue;
5721                         }
5722                         flag |= EXP_VARTILDE2;
5723                         reject++;
5724                         /* fall through */
5725                 case ':':
5726                         /*
5727                          * sort of a hack - expand tildes in variable
5728                          * assignments (after the first '=' and after ':'s).
5729                          */
5730                         if (*--p == '~') {
5731                                 goto tilde;
5732                         }
5733                         continue;
5734                 }
5735
5736                 switch (c) {
5737                 case CTLENDVAR: /* ??? */
5738                         goto breakloop;
5739                 case CTLQUOTEMARK:
5740                         /* "$@" syntax adherence hack */
5741                         if (
5742                                 !inquotes &&
5743                                 !memcmp(p, dolatstr, 4) &&
5744                                 (p[4] == CTLQUOTEMARK || (
5745                                         p[4] == CTLENDVAR &&
5746                                         p[5] == CTLQUOTEMARK
5747                                 ))
5748                         ) {
5749                                 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5750                                 goto start;
5751                         }
5752                         inquotes = !inquotes;
5753  addquote:
5754                         if (quotes) {
5755                                 p--;
5756                                 length++;
5757                                 startloc++;
5758                         }
5759                         break;
5760                 case CTLESC:
5761                         startloc++;
5762                         length++;
5763                         goto addquote;
5764                 case CTLVAR:
5765                         p = evalvar(p, flag, var_str_list);
5766                         goto start;
5767                 case CTLBACKQ:
5768                         c = 0;
5769                 case CTLBACKQ|CTLQUOTE:
5770                         expbackq(argbackq->n, c, quotes);
5771                         argbackq = argbackq->next;
5772                         goto start;
5773 #if ENABLE_ASH_MATH_SUPPORT
5774                 case CTLENDARI:
5775                         p--;
5776                         expari(quotes);
5777                         goto start;
5778 #endif
5779                 }
5780         }
5781  breakloop:
5782         ;
5783 }
5784
5785 static char *
5786 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5787         int zero)
5788 {
5789 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5790 // as part of a larger change when he added support for ${var/a/b}.
5791 // However, it broke # and % operators:
5792 //
5793 //var=ababcdcd
5794 //                 ok       bad
5795 //echo ${var#ab}   abcdcd   abcdcd
5796 //echo ${var##ab}  abcdcd   abcdcd
5797 //echo ${var#a*b}  abcdcd   ababcdcd  (!)
5798 //echo ${var##a*b} cdcd     cdcd
5799 //echo ${var#?}    babcdcd  ababcdcd  (!)
5800 //echo ${var##?}   babcdcd  babcdcd
5801 //echo ${var#*}    ababcdcd babcdcd   (!)
5802 //echo ${var##*}
5803 //echo ${var%cd}   ababcd   ababcd
5804 //echo ${var%%cd}  ababcd   abab      (!)
5805 //echo ${var%c*d}  ababcd   ababcd
5806 //echo ${var%%c*d} abab     ababcdcd  (!)
5807 //echo ${var%?}    ababcdc  ababcdc
5808 //echo ${var%%?}   ababcdc  ababcdcd  (!)
5809 //echo ${var%*}    ababcdcd ababcdcd
5810 //echo ${var%%*}
5811 //
5812 // Commenting it back out helped. Remove it completely if it really
5813 // is not needed.
5814
5815         char *loc, *loc2; //, *full;
5816         char c;
5817
5818         loc = startp;
5819         loc2 = rmesc;
5820         do {
5821                 int match; // = strlen(str);
5822                 const char *s = loc2;
5823
5824                 c = *loc2;
5825                 if (zero) {
5826                         *loc2 = '\0';
5827                         s = rmesc;
5828                 }
5829                 match = pmatch(str, s); // this line was deleted
5830
5831 //              // chop off end if its '*'
5832 //              full = strrchr(str, '*');
5833 //              if (full && full != str)
5834 //                      match--;
5835 //
5836 //              // If str starts with '*' replace with s.
5837 //              if ((*str == '*') && strlen(s) >= match) {
5838 //                      full = xstrdup(s);
5839 //                      strncpy(full+strlen(s)-match+1, str+1, match-1);
5840 //              } else
5841 //                      full = xstrndup(str, match);
5842 //              match = strncmp(s, full, strlen(full));
5843 //              free(full);
5844 //
5845                 *loc2 = c;
5846                 if (match) // if (!match)
5847                         return loc;
5848                 if (quotes && *loc == CTLESC)
5849                         loc++;
5850                 loc++;
5851                 loc2++;
5852         } while (c);
5853         return 0;
5854 }
5855
5856 static char *
5857 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5858         int zero)
5859 {
5860         int esc = 0;
5861         char *loc;
5862         char *loc2;
5863
5864         for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5865                 int match;
5866                 char c = *loc2;
5867                 const char *s = loc2;
5868                 if (zero) {
5869                         *loc2 = '\0';
5870                         s = rmesc;
5871                 }
5872                 match = pmatch(str, s);
5873                 *loc2 = c;
5874                 if (match)
5875                         return loc;
5876                 loc--;
5877                 if (quotes) {
5878                         if (--esc < 0) {
5879                                 esc = esclen(startp, loc);
5880                         }
5881                         if (esc % 2) {
5882                                 esc--;
5883                                 loc--;
5884                         }
5885                 }
5886         }
5887         return 0;
5888 }
5889
5890 static void varunset(const char *, const char *, const char *, int) NORETURN;
5891 static void
5892 varunset(const char *end, const char *var, const char *umsg, int varflags)
5893 {
5894         const char *msg;
5895         const char *tail;
5896
5897         tail = nullstr;
5898         msg = "parameter not set";
5899         if (umsg) {
5900                 if (*end == CTLENDVAR) {
5901                         if (varflags & VSNUL)
5902                                 tail = " or null";
5903                 } else
5904                         msg = umsg;
5905         }
5906         ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5907 }
5908
5909 #if ENABLE_ASH_BASH_COMPAT
5910 static char *
5911 parse_sub_pattern(char *arg, int inquotes)
5912 {
5913         char *idx, *repl = NULL;
5914         unsigned char c;
5915
5916         idx = arg;
5917         while (1) {
5918                 c = *arg;
5919                 if (!c)
5920                         break;
5921                 if (c == '/') {
5922                         /* Only the first '/' seen is our separator */
5923                         if (!repl) {
5924                                 repl = idx + 1;
5925                                 c = '\0';
5926                         }
5927                 }
5928                 *idx++ = c;
5929                 if (!inquotes && c == '\\' && arg[1] == '\\')
5930                         arg++; /* skip both \\, not just first one */
5931                 arg++;
5932         }
5933         *idx = c; /* NUL */
5934
5935         return repl;
5936 }
5937 #endif /* ENABLE_ASH_BASH_COMPAT */
5938
5939 static const char *
5940 subevalvar(char *p, char *str, int strloc, int subtype,
5941                 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5942 {
5943         struct nodelist *saveargbackq = argbackq;
5944         char *startp;
5945         char *loc;
5946         char *rmesc, *rmescend;
5947         USE_ASH_BASH_COMPAT(char *repl = NULL;)
5948         USE_ASH_BASH_COMPAT(char null = '\0';)
5949         USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5950         int saveherefd = herefd;
5951         int amount, workloc, resetloc;
5952         int zero;
5953         char *(*scan)(char*, char*, char*, char*, int, int);
5954
5955         herefd = -1;
5956         argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5957                         var_str_list);
5958         STPUTC('\0', expdest);
5959         herefd = saveherefd;
5960         argbackq = saveargbackq;
5961         startp = (char *)stackblock() + startloc;
5962
5963         switch (subtype) {
5964         case VSASSIGN:
5965                 setvar(str, startp, 0);
5966                 amount = startp - expdest;
5967                 STADJUST(amount, expdest);
5968                 return startp;
5969
5970 #if ENABLE_ASH_BASH_COMPAT
5971         case VSSUBSTR:
5972                 loc = str = stackblock() + strloc;
5973 // TODO: number() instead? It does error checking...
5974                 pos = atoi(loc);
5975                 len = str - startp - 1;
5976
5977                 /* *loc != '\0', guaranteed by parser */
5978                 if (quotes) {
5979                         char *ptr;
5980
5981                         /* We must adjust the length by the number of escapes we find. */
5982                         for (ptr = startp; ptr < (str - 1); ptr++) {
5983                                 if(*ptr == CTLESC) {
5984                                         len--;
5985                                         ptr++;
5986                                 }
5987                         }
5988                 }
5989                 orig_len = len;
5990
5991                 if (*loc++ == ':') {
5992 // TODO: number() instead? It does error checking...
5993                         len = atoi(loc);
5994                 } else {
5995                         len = orig_len;
5996                         while (*loc && *loc != ':')
5997                                 loc++;
5998                         if (*loc++ == ':')
5999 // TODO: number() instead? It does error checking...
6000                                 len = atoi(loc);
6001                 }
6002                 if (pos >= orig_len) {
6003                         pos = 0;
6004                         len = 0;
6005                 }
6006                 if (len > (orig_len - pos))
6007                         len = orig_len - pos;
6008
6009                 for (str = startp; pos; str++, pos--) {
6010                         if (quotes && *str == CTLESC)
6011                                 str++;
6012                 }
6013                 for (loc = startp; len; len--) {
6014                         if (quotes && *str == CTLESC)
6015                                 *loc++ = *str++;
6016                         *loc++ = *str++;
6017                 }
6018                 *loc = '\0';
6019                 amount = loc - expdest;
6020                 STADJUST(amount, expdest);
6021                 return loc;
6022 #endif
6023
6024         case VSQUESTION:
6025                 varunset(p, str, startp, varflags);
6026                 /* NOTREACHED */
6027         }
6028         resetloc = expdest - (char *)stackblock();
6029
6030         /* We'll comeback here if we grow the stack while handling
6031          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6032          * stack will need rebasing, and we'll need to remove our work
6033          * areas each time
6034          */
6035  USE_ASH_BASH_COMPAT(restart:)
6036
6037         amount = expdest - ((char *)stackblock() + resetloc);
6038         STADJUST(-amount, expdest);
6039         startp = (char *)stackblock() + startloc;
6040
6041         rmesc = startp;
6042         rmescend = (char *)stackblock() + strloc;
6043         if (quotes) {
6044                 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6045                 if (rmesc != startp) {
6046                         rmescend = expdest;
6047                         startp = (char *)stackblock() + startloc;
6048                 }
6049         }
6050         rmescend--;
6051         str = (char *)stackblock() + strloc;
6052         preglob(str, varflags & VSQUOTE, 0);
6053         workloc = expdest - (char *)stackblock();
6054
6055 #if ENABLE_ASH_BASH_COMPAT
6056         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6057                 char *idx, *end, *restart_detect;
6058
6059                 if(!repl) {
6060                         repl = parse_sub_pattern(str, varflags & VSQUOTE);
6061                         if (!repl)
6062                                 repl = &null;
6063                 }
6064
6065                 /* If there's no pattern to match, return the expansion unmolested */
6066                 if (*str == '\0')
6067                         return 0;
6068
6069                 len = 0;
6070                 idx = startp;
6071                 end = str - 1;
6072                 while (idx < end) {
6073                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6074                         if (!loc) {
6075                                 /* No match, advance */
6076                                 restart_detect = stackblock();
6077                                 STPUTC(*idx, expdest);
6078                                 if (quotes && *idx == CTLESC) {
6079                                         idx++;
6080                                         len++;
6081                                         STPUTC(*idx, expdest);
6082                                 }
6083                                 if (stackblock() != restart_detect)
6084                                         goto restart;
6085                                 idx++;
6086                                 len++;
6087                                 rmesc++;
6088                                 continue;
6089                         }
6090
6091                         if (subtype == VSREPLACEALL) {
6092                                 while (idx < loc) {
6093                                         if (quotes && *idx == CTLESC)
6094                                                 idx++;
6095                                         idx++;
6096                                         rmesc++;
6097                                 }
6098                         } else
6099                                 idx = loc;
6100
6101                         for (loc = repl; *loc; loc++) {
6102                                 restart_detect = stackblock();
6103                                 STPUTC(*loc, expdest);
6104                                 if (stackblock() != restart_detect)
6105                                         goto restart;
6106                                 len++;
6107                         }
6108
6109                         if (subtype == VSREPLACE) {
6110                                 while (*idx) {
6111                                         restart_detect = stackblock();
6112                                         STPUTC(*idx, expdest);
6113                                         if (stackblock() != restart_detect)
6114                                                 goto restart;
6115                                         len++;
6116                                         idx++;
6117                                 }
6118                                 break;
6119                         }
6120                 }
6121
6122                 /* We've put the replaced text into a buffer at workloc, now
6123                  * move it to the right place and adjust the stack.
6124                  */
6125                 startp = stackblock() + startloc;
6126                 STPUTC('\0', expdest);
6127                 memmove(startp, stackblock() + workloc, len);
6128                 startp[len++] = '\0';
6129                 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6130                 STADJUST(-amount, expdest);
6131                 return startp;
6132         }
6133 #endif /* ENABLE_ASH_BASH_COMPAT */
6134
6135         subtype -= VSTRIMRIGHT;
6136 #if DEBUG
6137         if (subtype < 0 || subtype > 7)
6138                 abort();
6139 #endif
6140         /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6141         zero = subtype >> 1;
6142         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6143         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6144
6145         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6146         if (loc) {
6147                 if (zero) {
6148                         memmove(startp, loc, str - loc);
6149                         loc = startp + (str - loc) - 1;
6150                 }
6151                 *loc = '\0';
6152                 amount = loc - expdest;
6153                 STADJUST(amount, expdest);
6154         }
6155         return loc;
6156 }
6157
6158 /*
6159  * Add the value of a specialized variable to the stack string.
6160  */
6161 static ssize_t
6162 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6163 {
6164         int num;
6165         char *p;
6166         int i;
6167         int sep = 0;
6168         int sepq = 0;
6169         ssize_t len = 0;
6170         char **ap;
6171         int syntax;
6172         int quoted = varflags & VSQUOTE;
6173         int subtype = varflags & VSTYPE;
6174         int quotes = flags & (EXP_FULL | EXP_CASE);
6175
6176         if (quoted && (flags & EXP_FULL))
6177                 sep = 1 << CHAR_BIT;
6178
6179         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6180         switch (*name) {
6181         case '$':
6182                 num = rootpid;
6183                 goto numvar;
6184         case '?':
6185                 num = exitstatus;
6186                 goto numvar;
6187         case '#':
6188                 num = shellparam.nparam;
6189                 goto numvar;
6190         case '!':
6191                 num = backgndpid;
6192                 if (num == 0)
6193                         return -1;
6194  numvar:
6195                 len = cvtnum(num);
6196                 break;
6197         case '-':
6198                 p = makestrspace(NOPTS, expdest);
6199                 for (i = NOPTS - 1; i >= 0; i--) {
6200                         if (optlist[i]) {
6201                                 USTPUTC(optletters(i), p);
6202                                 len++;
6203                         }
6204                 }
6205                 expdest = p;
6206                 break;
6207         case '@':
6208                 if (sep)
6209                         goto param;
6210                 /* fall through */
6211         case '*':
6212                 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6213                 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6214                         sepq = 1;
6215  param:
6216                 ap = shellparam.p;
6217                 if (!ap)
6218                         return -1;
6219                 while ((p = *ap++)) {
6220                         size_t partlen;
6221
6222                         partlen = strlen(p);
6223                         len += partlen;
6224
6225                         if (!(subtype == VSPLUS || subtype == VSLENGTH))
6226                                 memtodest(p, partlen, syntax, quotes);
6227
6228                         if (*ap && sep) {
6229                                 char *q;
6230
6231                                 len++;
6232                                 if (subtype == VSPLUS || subtype == VSLENGTH) {
6233                                         continue;
6234                                 }
6235                                 q = expdest;
6236                                 if (sepq)
6237                                         STPUTC(CTLESC, q);
6238                                 STPUTC(sep, q);
6239                                 expdest = q;
6240                         }
6241                 }
6242                 return len;
6243         case '0':
6244         case '1':
6245         case '2':
6246         case '3':
6247         case '4':
6248         case '5':
6249         case '6':
6250         case '7':
6251         case '8':
6252         case '9':
6253 // TODO: number() instead? It does error checking...
6254                 num = atoi(name);
6255                 if (num < 0 || num > shellparam.nparam)
6256                         return -1;
6257                 p = num ? shellparam.p[num - 1] : arg0;
6258                 goto value;
6259         default:
6260                 /* NB: name has form "VAR=..." */
6261
6262                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6263                  * which should be considered before we check variables. */
6264                 if (var_str_list) {
6265                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6266                         p = NULL;
6267                         do {
6268                                 char *str, *eq;
6269                                 str = var_str_list->text;
6270                                 eq = strchr(str, '=');
6271                                 if (!eq) /* stop at first non-assignment */
6272                                         break;
6273                                 eq++;
6274                                 if (name_len == (unsigned)(eq - str)
6275                                  && strncmp(str, name, name_len) == 0) {
6276                                         p = eq;
6277                                         /* goto value; - WRONG! */
6278                                         /* think "A=1 A=2 B=$A" */
6279                                 }
6280                                 var_str_list = var_str_list->next;
6281                         } while (var_str_list);
6282                         if (p)
6283                                 goto value;
6284                 }
6285                 p = lookupvar(name);
6286  value:
6287                 if (!p)
6288                         return -1;
6289
6290                 len = strlen(p);
6291                 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6292                         memtodest(p, len, syntax, quotes);
6293                 return len;
6294         }
6295
6296         if (subtype == VSPLUS || subtype == VSLENGTH)
6297                 STADJUST(-len, expdest);
6298         return len;
6299 }
6300
6301 /*
6302  * Expand a variable, and return a pointer to the next character in the
6303  * input string.
6304  */
6305 static char *
6306 evalvar(char *p, int flag, struct strlist *var_str_list)
6307 {
6308         char varflags;
6309         char subtype;
6310         char quoted;
6311         char easy;
6312         char *var;
6313         int patloc;
6314         int startloc;
6315         ssize_t varlen;
6316
6317         varflags = *p++;
6318         subtype = varflags & VSTYPE;
6319         quoted = varflags & VSQUOTE;
6320         var = p;
6321         easy = (!quoted || (*var == '@' && shellparam.nparam));
6322         startloc = expdest - (char *)stackblock();
6323         p = strchr(p, '=') + 1;
6324
6325  again:
6326         varlen = varvalue(var, varflags, flag, var_str_list);
6327         if (varflags & VSNUL)
6328                 varlen--;
6329
6330         if (subtype == VSPLUS) {
6331                 varlen = -1 - varlen;
6332                 goto vsplus;
6333         }
6334
6335         if (subtype == VSMINUS) {
6336  vsplus:
6337                 if (varlen < 0) {
6338                         argstr(
6339                                 p, flag | EXP_TILDE |
6340                                         (quoted ?  EXP_QWORD : EXP_WORD),
6341                                 var_str_list
6342                         );
6343                         goto end;
6344                 }
6345                 if (easy)
6346                         goto record;
6347                 goto end;
6348         }
6349
6350         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6351                 if (varlen < 0) {
6352                         if (subevalvar(p, var, /* strloc: */ 0,
6353                                         subtype, startloc, varflags,
6354                                         /* quotes: */ 0,
6355                                         var_str_list)
6356                         ) {
6357                                 varflags &= ~VSNUL;
6358                                 /*
6359                                  * Remove any recorded regions beyond
6360                                  * start of variable
6361                                  */
6362                                 removerecordregions(startloc);
6363                                 goto again;
6364                         }
6365                         goto end;
6366                 }
6367                 if (easy)
6368                         goto record;
6369                 goto end;
6370         }
6371
6372         if (varlen < 0 && uflag)
6373                 varunset(p, var, 0, 0);
6374
6375         if (subtype == VSLENGTH) {
6376                 cvtnum(varlen > 0 ? varlen : 0);
6377                 goto record;
6378         }
6379
6380         if (subtype == VSNORMAL) {
6381                 if (easy)
6382                         goto record;
6383                 goto end;
6384         }
6385
6386 #if DEBUG
6387         switch (subtype) {
6388         case VSTRIMLEFT:
6389         case VSTRIMLEFTMAX:
6390         case VSTRIMRIGHT:
6391         case VSTRIMRIGHTMAX:
6392 #if ENABLE_ASH_BASH_COMPAT
6393         case VSSUBSTR:
6394         case VSREPLACE:
6395         case VSREPLACEALL:
6396 #endif
6397                 break;
6398         default:
6399                 abort();
6400         }
6401 #endif
6402
6403         if (varlen >= 0) {
6404                 /*
6405                  * Terminate the string and start recording the pattern
6406                  * right after it
6407                  */
6408                 STPUTC('\0', expdest);
6409                 patloc = expdest - (char *)stackblock();
6410                 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6411                                 startloc, varflags,
6412                                 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6413                                 var_str_list)
6414                 ) {
6415                         int amount = expdest - (
6416                                 (char *)stackblock() + patloc - 1
6417                         );
6418                         STADJUST(-amount, expdest);
6419                 }
6420                 /* Remove any recorded regions beyond start of variable */
6421                 removerecordregions(startloc);
6422  record:
6423                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6424         }
6425
6426  end:
6427         if (subtype != VSNORMAL) {      /* skip to end of alternative */
6428                 int nesting = 1;
6429                 for (;;) {
6430                         char c = *p++;
6431                         if (c == CTLESC)
6432                                 p++;
6433                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6434                                 if (varlen >= 0)
6435                                         argbackq = argbackq->next;
6436                         } else if (c == CTLVAR) {
6437                                 if ((*p++ & VSTYPE) != VSNORMAL)
6438                                         nesting++;
6439                         } else if (c == CTLENDVAR) {
6440                                 if (--nesting == 0)
6441                                         break;
6442                         }
6443                 }
6444         }
6445         return p;
6446 }
6447
6448 /*
6449  * Break the argument string into pieces based upon IFS and add the
6450  * strings to the argument list.  The regions of the string to be
6451  * searched for IFS characters have been stored by recordregion.
6452  */
6453 static void
6454 ifsbreakup(char *string, struct arglist *arglist)
6455 {
6456         struct ifsregion *ifsp;
6457         struct strlist *sp;
6458         char *start;
6459         char *p;
6460         char *q;
6461         const char *ifs, *realifs;
6462         int ifsspc;
6463         int nulonly;
6464
6465         start = string;
6466         if (ifslastp != NULL) {
6467                 ifsspc = 0;
6468                 nulonly = 0;
6469                 realifs = ifsset() ? ifsval() : defifs;
6470                 ifsp = &ifsfirst;
6471                 do {
6472                         p = string + ifsp->begoff;
6473                         nulonly = ifsp->nulonly;
6474                         ifs = nulonly ? nullstr : realifs;
6475                         ifsspc = 0;
6476                         while (p < string + ifsp->endoff) {
6477                                 q = p;
6478                                 if (*p == CTLESC)
6479                                         p++;
6480                                 if (!strchr(ifs, *p)) {
6481                                         p++;
6482                                         continue;
6483                                 }
6484                                 if (!nulonly)
6485                                         ifsspc = (strchr(defifs, *p) != NULL);
6486                                 /* Ignore IFS whitespace at start */
6487                                 if (q == start && ifsspc) {
6488                                         p++;
6489                                         start = p;
6490                                         continue;
6491                                 }
6492                                 *q = '\0';
6493                                 sp = stzalloc(sizeof(*sp));
6494                                 sp->text = start;
6495                                 *arglist->lastp = sp;
6496                                 arglist->lastp = &sp->next;
6497                                 p++;
6498                                 if (!nulonly) {
6499                                         for (;;) {
6500                                                 if (p >= string + ifsp->endoff) {
6501                                                         break;
6502                                                 }
6503                                                 q = p;
6504                                                 if (*p == CTLESC)
6505                                                         p++;
6506                                                 if (strchr(ifs, *p) == NULL) {
6507                                                         p = q;
6508                                                         break;
6509                                                 }
6510                                                 if (strchr(defifs, *p) == NULL) {
6511                                                         if (ifsspc) {
6512                                                                 p++;
6513                                                                 ifsspc = 0;
6514                                                         } else {
6515                                                                 p = q;
6516                                                                 break;
6517                                                         }
6518                                                 } else
6519                                                         p++;
6520                                         }
6521                                 }
6522                                 start = p;
6523                         } /* while */
6524                         ifsp = ifsp->next;
6525                 } while (ifsp != NULL);
6526                 if (nulonly)
6527                         goto add;
6528         }
6529
6530         if (!*start)
6531                 return;
6532
6533  add:
6534         sp = stzalloc(sizeof(*sp));
6535         sp->text = start;
6536         *arglist->lastp = sp;
6537         arglist->lastp = &sp->next;
6538 }
6539
6540 static void
6541 ifsfree(void)
6542 {
6543         struct ifsregion *p;
6544
6545         INT_OFF;
6546         p = ifsfirst.next;
6547         do {
6548                 struct ifsregion *ifsp;
6549                 ifsp = p->next;
6550                 free(p);
6551                 p = ifsp;
6552         } while (p);
6553         ifslastp = NULL;
6554         ifsfirst.next = NULL;
6555         INT_ON;
6556 }
6557
6558 /*
6559  * Add a file name to the list.
6560  */
6561 static void
6562 addfname(const char *name)
6563 {
6564         struct strlist *sp;
6565
6566         sp = stzalloc(sizeof(*sp));
6567         sp->text = ststrdup(name);
6568         *exparg.lastp = sp;
6569         exparg.lastp = &sp->next;
6570 }
6571
6572 static char *expdir;
6573
6574 /*
6575  * Do metacharacter (i.e. *, ?, [...]) expansion.
6576  */
6577 static void
6578 expmeta(char *enddir, char *name)
6579 {
6580         char *p;
6581         const char *cp;
6582         char *start;
6583         char *endname;
6584         int metaflag;
6585         struct stat statb;
6586         DIR *dirp;
6587         struct dirent *dp;
6588         int atend;
6589         int matchdot;
6590
6591         metaflag = 0;
6592         start = name;
6593         for (p = name; *p; p++) {
6594                 if (*p == '*' || *p == '?')
6595                         metaflag = 1;
6596                 else if (*p == '[') {
6597                         char *q = p + 1;
6598                         if (*q == '!')
6599                                 q++;
6600                         for (;;) {
6601                                 if (*q == '\\')
6602                                         q++;
6603                                 if (*q == '/' || *q == '\0')
6604                                         break;
6605                                 if (*++q == ']') {
6606                                         metaflag = 1;
6607                                         break;
6608                                 }
6609                         }
6610                 } else if (*p == '\\')
6611                         p++;
6612                 else if (*p == '/') {
6613                         if (metaflag)
6614                                 goto out;
6615                         start = p + 1;
6616                 }
6617         }
6618  out:
6619         if (metaflag == 0) {    /* we've reached the end of the file name */
6620                 if (enddir != expdir)
6621                         metaflag++;
6622                 p = name;
6623                 do {
6624                         if (*p == '\\')
6625                                 p++;
6626                         *enddir++ = *p;
6627                 } while (*p++);
6628                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6629                         addfname(expdir);
6630                 return;
6631         }
6632         endname = p;
6633         if (name < start) {
6634                 p = name;
6635                 do {
6636                         if (*p == '\\')
6637                                 p++;
6638                         *enddir++ = *p++;
6639                 } while (p < start);
6640         }
6641         if (enddir == expdir) {
6642                 cp = ".";
6643         } else if (enddir == expdir + 1 && *expdir == '/') {
6644                 cp = "/";
6645         } else {
6646                 cp = expdir;
6647                 enddir[-1] = '\0';
6648         }
6649         dirp = opendir(cp);
6650         if (dirp == NULL)
6651                 return;
6652         if (enddir != expdir)
6653                 enddir[-1] = '/';
6654         if (*endname == 0) {
6655                 atend = 1;
6656         } else {
6657                 atend = 0;
6658                 *endname++ = '\0';
6659         }
6660         matchdot = 0;
6661         p = start;
6662         if (*p == '\\')
6663                 p++;
6664         if (*p == '.')
6665                 matchdot++;
6666         while (!intpending && (dp = readdir(dirp)) != NULL) {
6667                 if (dp->d_name[0] == '.' && !matchdot)
6668                         continue;
6669                 if (pmatch(start, dp->d_name)) {
6670                         if (atend) {
6671                                 strcpy(enddir, dp->d_name);
6672                                 addfname(expdir);
6673                         } else {
6674                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6675                                         continue;
6676                                 p[-1] = '/';
6677                                 expmeta(p, endname);
6678                         }
6679                 }
6680         }
6681         closedir(dirp);
6682         if (!atend)
6683                 endname[-1] = '/';
6684 }
6685
6686 static struct strlist *
6687 msort(struct strlist *list, int len)
6688 {
6689         struct strlist *p, *q = NULL;
6690         struct strlist **lpp;
6691         int half;
6692         int n;
6693
6694         if (len <= 1)
6695                 return list;
6696         half = len >> 1;
6697         p = list;
6698         for (n = half; --n >= 0;) {
6699                 q = p;
6700                 p = p->next;
6701         }
6702         q->next = NULL;                 /* terminate first half of list */
6703         q = msort(list, half);          /* sort first half of list */
6704         p = msort(p, len - half);               /* sort second half */
6705         lpp = &list;
6706         for (;;) {
6707 #if ENABLE_LOCALE_SUPPORT
6708                 if (strcoll(p->text, q->text) < 0)
6709 #else
6710                 if (strcmp(p->text, q->text) < 0)
6711 #endif
6712                                                 {
6713                         *lpp = p;
6714                         lpp = &p->next;
6715                         p = *lpp;
6716                         if (p == NULL) {
6717                                 *lpp = q;
6718                                 break;
6719                         }
6720                 } else {
6721                         *lpp = q;
6722                         lpp = &q->next;
6723                         q = *lpp;
6724                         if (q == NULL) {
6725                                 *lpp = p;
6726                                 break;
6727                         }
6728                 }
6729         }
6730         return list;
6731 }
6732
6733 /*
6734  * Sort the results of file name expansion.  It calculates the number of
6735  * strings to sort and then calls msort (short for merge sort) to do the
6736  * work.
6737  */
6738 static struct strlist *
6739 expsort(struct strlist *str)
6740 {
6741         int len;
6742         struct strlist *sp;
6743
6744         len = 0;
6745         for (sp = str; sp; sp = sp->next)
6746                 len++;
6747         return msort(str, len);
6748 }
6749
6750 static void
6751 expandmeta(struct strlist *str /*, int flag*/)
6752 {
6753         static const char metachars[] ALIGN1 = {
6754                 '*', '?', '[', 0
6755         };
6756         /* TODO - EXP_REDIR */
6757
6758         while (str) {
6759                 struct strlist **savelastp;
6760                 struct strlist *sp;
6761                 char *p;
6762
6763                 if (fflag)
6764                         goto nometa;
6765                 if (!strpbrk(str->text, metachars))
6766                         goto nometa;
6767                 savelastp = exparg.lastp;
6768
6769                 INT_OFF;
6770                 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6771                 {
6772                         int i = strlen(str->text);
6773                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6774                 }
6775
6776                 expmeta(expdir, p);
6777                 free(expdir);
6778                 if (p != str->text)
6779                         free(p);
6780                 INT_ON;
6781                 if (exparg.lastp == savelastp) {
6782                         /*
6783                          * no matches
6784                          */
6785  nometa:
6786                         *exparg.lastp = str;
6787                         rmescapes(str->text);
6788                         exparg.lastp = &str->next;
6789                 } else {
6790                         *exparg.lastp = NULL;
6791                         *savelastp = sp = expsort(*savelastp);
6792                         while (sp->next != NULL)
6793                                 sp = sp->next;
6794                         exparg.lastp = &sp->next;
6795                 }
6796                 str = str->next;
6797         }
6798 }
6799
6800 /*
6801  * Perform variable substitution and command substitution on an argument,
6802  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
6803  * perform splitting and file name expansion.  When arglist is NULL, perform
6804  * here document expansion.
6805  */
6806 static void
6807 expandarg(union node *arg, struct arglist *arglist, int flag)
6808 {
6809         struct strlist *sp;
6810         char *p;
6811
6812         argbackq = arg->narg.backquote;
6813         STARTSTACKSTR(expdest);
6814         ifsfirst.next = NULL;
6815         ifslastp = NULL;
6816         argstr(arg->narg.text, flag,
6817                         /* var_str_list: */ arglist ? arglist->list : NULL);
6818         p = _STPUTC('\0', expdest);
6819         expdest = p - 1;
6820         if (arglist == NULL) {
6821                 return;                 /* here document expanded */
6822         }
6823         p = grabstackstr(p);
6824         exparg.lastp = &exparg.list;
6825         /*
6826          * TODO - EXP_REDIR
6827          */
6828         if (flag & EXP_FULL) {
6829                 ifsbreakup(p, &exparg);
6830                 *exparg.lastp = NULL;
6831                 exparg.lastp = &exparg.list;
6832                 expandmeta(exparg.list /*, flag*/);
6833         } else {
6834                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6835                         rmescapes(p);
6836                 sp = stzalloc(sizeof(*sp));
6837                 sp->text = p;
6838                 *exparg.lastp = sp;
6839                 exparg.lastp = &sp->next;
6840         }
6841         if (ifsfirst.next)
6842                 ifsfree();
6843         *exparg.lastp = NULL;
6844         if (exparg.list) {
6845                 *arglist->lastp = exparg.list;
6846                 arglist->lastp = exparg.lastp;
6847         }
6848 }
6849
6850 /*
6851  * Expand shell variables and backquotes inside a here document.
6852  */
6853 static void
6854 expandhere(union node *arg, int fd)
6855 {
6856         herefd = fd;
6857         expandarg(arg, (struct arglist *)NULL, 0);
6858         full_write(fd, stackblock(), expdest - (char *)stackblock());
6859 }
6860
6861 /*
6862  * Returns true if the pattern matches the string.
6863  */
6864 static int
6865 patmatch(char *pattern, const char *string)
6866 {
6867         return pmatch(preglob(pattern, 0, 0), string);
6868 }
6869
6870 /*
6871  * See if a pattern matches in a case statement.
6872  */
6873 static int
6874 casematch(union node *pattern, char *val)
6875 {
6876         struct stackmark smark;
6877         int result;
6878
6879         setstackmark(&smark);
6880         argbackq = pattern->narg.backquote;
6881         STARTSTACKSTR(expdest);
6882         ifslastp = NULL;
6883         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6884                         /* var_str_list: */ NULL);
6885         STACKSTRNUL(expdest);
6886         result = patmatch(stackblock(), val);
6887         popstackmark(&smark);
6888         return result;
6889 }
6890
6891
6892 /* ============ find_command */
6893
6894 struct builtincmd {
6895         const char *name;
6896         int (*builtin)(int, char **);
6897         /* unsigned flags; */
6898 };
6899 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6900 /* "regular" builtins always take precedence over commands,
6901  * regardless of PATH=....%builtin... position */
6902 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6903 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
6904
6905 struct cmdentry {
6906         smallint cmdtype;       /* CMDxxx */
6907         union param {
6908                 int index;
6909                 /* index >= 0 for commands without path (slashes) */
6910                 /* (TODO: what exactly does the value mean? PATH position?) */
6911                 /* index == -1 for commands with slashes */
6912                 /* index == (-2 - applet_no) for NOFORK applets */
6913                 const struct builtincmd *cmd;
6914                 struct funcnode *func;
6915         } u;
6916 };
6917 /* values of cmdtype */
6918 #define CMDUNKNOWN      -1      /* no entry in table for command */
6919 #define CMDNORMAL       0       /* command is an executable program */
6920 #define CMDFUNCTION     1       /* command is a shell function */
6921 #define CMDBUILTIN      2       /* command is a shell builtin */
6922
6923 /* action to find_command() */
6924 #define DO_ERR          0x01    /* prints errors */
6925 #define DO_ABS          0x02    /* checks absolute paths */
6926 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
6927 #define DO_ALTPATH      0x08    /* using alternate path */
6928 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
6929
6930 static void find_command(char *, struct cmdentry *, int, const char *);
6931
6932
6933 /* ============ Hashing commands */
6934
6935 /*
6936  * When commands are first encountered, they are entered in a hash table.
6937  * This ensures that a full path search will not have to be done for them
6938  * on each invocation.
6939  *
6940  * We should investigate converting to a linear search, even though that
6941  * would make the command name "hash" a misnomer.
6942  */
6943
6944 struct tblentry {
6945         struct tblentry *next;  /* next entry in hash chain */
6946         union param param;      /* definition of builtin function */
6947         smallint cmdtype;       /* CMDxxx */
6948         char rehash;            /* if set, cd done since entry created */
6949         char cmdname[1];        /* name of command */
6950 };
6951
6952 static struct tblentry **cmdtable;
6953 #define INIT_G_cmdtable() do { \
6954         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6955 } while (0)
6956
6957 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
6958
6959
6960 static void
6961 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6962 {
6963         int repeated = 0;
6964
6965 #if ENABLE_FEATURE_SH_STANDALONE
6966         if (applet_no >= 0) {
6967                 if (APPLET_IS_NOEXEC(applet_no))
6968                         run_applet_no_and_exit(applet_no, argv);
6969                 /* re-exec ourselves with the new arguments */
6970                 execve(bb_busybox_exec_path, argv, envp);
6971                 /* If they called chroot or otherwise made the binary no longer
6972                  * executable, fall through */
6973         }
6974 #endif
6975
6976  repeat:
6977 #ifdef SYSV
6978         do {
6979                 execve(cmd, argv, envp);
6980         } while (errno == EINTR);
6981 #else
6982         execve(cmd, argv, envp);
6983 #endif
6984         if (repeated) {
6985                 free(argv);
6986                 return;
6987         }
6988         if (errno == ENOEXEC) {
6989                 char **ap;
6990                 char **new;
6991
6992                 for (ap = argv; *ap; ap++)
6993                         continue;
6994                 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
6995                 ap[1] = cmd;
6996                 ap[0] = cmd = (char *)DEFAULT_SHELL;
6997                 ap += 2;
6998                 argv++;
6999                 while ((*ap++ = *argv++) != NULL)
7000                         continue;
7001                 argv = new;
7002                 repeated++;
7003                 goto repeat;
7004         }
7005 }
7006
7007 /*
7008  * Exec a program.  Never returns.  If you change this routine, you may
7009  * have to change the find_command routine as well.
7010  */
7011 static void shellexec(char **, const char *, int) NORETURN;
7012 static void
7013 shellexec(char **argv, const char *path, int idx)
7014 {
7015         char *cmdname;
7016         int e;
7017         char **envp;
7018         int exerrno;
7019 #if ENABLE_FEATURE_SH_STANDALONE
7020         int applet_no = -1;
7021 #endif
7022
7023         clearredir(/*drop:*/ 1);
7024         envp = listvars(VEXPORT, VUNSET, 0);
7025         if (strchr(argv[0], '/') != NULL
7026 #if ENABLE_FEATURE_SH_STANDALONE
7027          || (applet_no = find_applet_by_name(argv[0])) >= 0
7028 #endif
7029         ) {
7030                 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7031                 e = errno;
7032         } else {
7033                 e = ENOENT;
7034                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7035                         if (--idx < 0 && pathopt == NULL) {
7036                                 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7037                                 if (errno != ENOENT && errno != ENOTDIR)
7038                                         e = errno;
7039                         }
7040                         stunalloc(cmdname);
7041                 }
7042         }
7043
7044         /* Map to POSIX errors */
7045         switch (e) {
7046         case EACCES:
7047                 exerrno = 126;
7048                 break;
7049         case ENOENT:
7050                 exerrno = 127;
7051                 break;
7052         default:
7053                 exerrno = 2;
7054                 break;
7055         }
7056         exitstatus = exerrno;
7057         TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7058                 argv[0], e, suppressint));
7059         ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7060         /* NOTREACHED */
7061 }
7062
7063 static void
7064 printentry(struct tblentry *cmdp)
7065 {
7066         int idx;
7067         const char *path;
7068         char *name;
7069
7070         idx = cmdp->param.index;
7071         path = pathval();
7072         do {
7073                 name = padvance(&path, cmdp->cmdname);
7074                 stunalloc(name);
7075         } while (--idx >= 0);
7076         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7077 }
7078
7079 /*
7080  * Clear out command entries.  The argument specifies the first entry in
7081  * PATH which has changed.
7082  */
7083 static void
7084 clearcmdentry(int firstchange)
7085 {
7086         struct tblentry **tblp;
7087         struct tblentry **pp;
7088         struct tblentry *cmdp;
7089
7090         INT_OFF;
7091         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7092                 pp = tblp;
7093                 while ((cmdp = *pp) != NULL) {
7094                         if ((cmdp->cmdtype == CMDNORMAL &&
7095                              cmdp->param.index >= firstchange)
7096                          || (cmdp->cmdtype == CMDBUILTIN &&
7097                              builtinloc >= firstchange)
7098                         ) {
7099                                 *pp = cmdp->next;
7100                                 free(cmdp);
7101                         } else {
7102                                 pp = &cmdp->next;
7103                         }
7104                 }
7105         }
7106         INT_ON;
7107 }
7108
7109 /*
7110  * Locate a command in the command hash table.  If "add" is nonzero,
7111  * add the command to the table if it is not already present.  The
7112  * variable "lastcmdentry" is set to point to the address of the link
7113  * pointing to the entry, so that delete_cmd_entry can delete the
7114  * entry.
7115  *
7116  * Interrupts must be off if called with add != 0.
7117  */
7118 static struct tblentry **lastcmdentry;
7119
7120 static struct tblentry *
7121 cmdlookup(const char *name, int add)
7122 {
7123         unsigned int hashval;
7124         const char *p;
7125         struct tblentry *cmdp;
7126         struct tblentry **pp;
7127
7128         p = name;
7129         hashval = (unsigned char)*p << 4;
7130         while (*p)
7131                 hashval += (unsigned char)*p++;
7132         hashval &= 0x7FFF;
7133         pp = &cmdtable[hashval % CMDTABLESIZE];
7134         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7135                 if (strcmp(cmdp->cmdname, name) == 0)
7136                         break;
7137                 pp = &cmdp->next;
7138         }
7139         if (add && cmdp == NULL) {
7140                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7141                                 + strlen(name)
7142                                 /* + 1 - already done because
7143                                  * tblentry::cmdname is char[1] */);
7144                 /*cmdp->next = NULL; - ckzalloc did it */
7145                 cmdp->cmdtype = CMDUNKNOWN;
7146                 strcpy(cmdp->cmdname, name);
7147         }
7148         lastcmdentry = pp;
7149         return cmdp;
7150 }
7151
7152 /*
7153  * Delete the command entry returned on the last lookup.
7154  */
7155 static void
7156 delete_cmd_entry(void)
7157 {
7158         struct tblentry *cmdp;
7159
7160         INT_OFF;
7161         cmdp = *lastcmdentry;
7162         *lastcmdentry = cmdp->next;
7163         if (cmdp->cmdtype == CMDFUNCTION)
7164                 freefunc(cmdp->param.func);
7165         free(cmdp);
7166         INT_ON;
7167 }
7168
7169 /*
7170  * Add a new command entry, replacing any existing command entry for
7171  * the same name - except special builtins.
7172  */
7173 static void
7174 addcmdentry(char *name, struct cmdentry *entry)
7175 {
7176         struct tblentry *cmdp;
7177
7178         cmdp = cmdlookup(name, 1);
7179         if (cmdp->cmdtype == CMDFUNCTION) {
7180                 freefunc(cmdp->param.func);
7181         }
7182         cmdp->cmdtype = entry->cmdtype;
7183         cmdp->param = entry->u;
7184         cmdp->rehash = 0;
7185 }
7186
7187 static int
7188 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7189 {
7190         struct tblentry **pp;
7191         struct tblentry *cmdp;
7192         int c;
7193         struct cmdentry entry;
7194         char *name;
7195
7196         if (nextopt("r") != '\0') {
7197                 clearcmdentry(0);
7198                 return 0;
7199         }
7200
7201         if (*argptr == NULL) {
7202                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7203                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7204                                 if (cmdp->cmdtype == CMDNORMAL)
7205                                         printentry(cmdp);
7206                         }
7207                 }
7208                 return 0;
7209         }
7210
7211         c = 0;
7212         while ((name = *argptr) != NULL) {
7213                 cmdp = cmdlookup(name, 0);
7214                 if (cmdp != NULL
7215                  && (cmdp->cmdtype == CMDNORMAL
7216                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7217                 ) {
7218                         delete_cmd_entry();
7219                 }
7220                 find_command(name, &entry, DO_ERR, pathval());
7221                 if (entry.cmdtype == CMDUNKNOWN)
7222                         c = 1;
7223                 argptr++;
7224         }
7225         return c;
7226 }
7227
7228 /*
7229  * Called when a cd is done.  Marks all commands so the next time they
7230  * are executed they will be rehashed.
7231  */
7232 static void
7233 hashcd(void)
7234 {
7235         struct tblentry **pp;
7236         struct tblentry *cmdp;
7237
7238         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7239                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7240                         if (cmdp->cmdtype == CMDNORMAL
7241                          || (cmdp->cmdtype == CMDBUILTIN
7242                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7243                              && builtinloc > 0)
7244                         ) {
7245                                 cmdp->rehash = 1;
7246                         }
7247                 }
7248         }
7249 }
7250
7251 /*
7252  * Fix command hash table when PATH changed.
7253  * Called before PATH is changed.  The argument is the new value of PATH;
7254  * pathval() still returns the old value at this point.
7255  * Called with interrupts off.
7256  */
7257 static void
7258 changepath(const char *new)
7259 {
7260         const char *old;
7261         int firstchange;
7262         int idx;
7263         int idx_bltin;
7264
7265         old = pathval();
7266         firstchange = 9999;     /* assume no change */
7267         idx = 0;
7268         idx_bltin = -1;
7269         for (;;) {
7270                 if (*old != *new) {
7271                         firstchange = idx;
7272                         if ((*old == '\0' && *new == ':')
7273                          || (*old == ':' && *new == '\0'))
7274                                 firstchange++;
7275                         old = new;      /* ignore subsequent differences */
7276                 }
7277                 if (*new == '\0')
7278                         break;
7279                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7280                         idx_bltin = idx;
7281                 if (*new == ':')
7282                         idx++;
7283                 new++, old++;
7284         }
7285         if (builtinloc < 0 && idx_bltin >= 0)
7286                 builtinloc = idx_bltin;             /* zap builtins */
7287         if (builtinloc >= 0 && idx_bltin < 0)
7288                 firstchange = 0;
7289         clearcmdentry(firstchange);
7290         builtinloc = idx_bltin;
7291 }
7292
7293 #define TEOF 0
7294 #define TNL 1
7295 #define TREDIR 2
7296 #define TWORD 3
7297 #define TSEMI 4
7298 #define TBACKGND 5
7299 #define TAND 6
7300 #define TOR 7
7301 #define TPIPE 8
7302 #define TLP 9
7303 #define TRP 10
7304 #define TENDCASE 11
7305 #define TENDBQUOTE 12
7306 #define TNOT 13
7307 #define TCASE 14
7308 #define TDO 15
7309 #define TDONE 16
7310 #define TELIF 17
7311 #define TELSE 18
7312 #define TESAC 19
7313 #define TFI 20
7314 #define TFOR 21
7315 #define TIF 22
7316 #define TIN 23
7317 #define TTHEN 24
7318 #define TUNTIL 25
7319 #define TWHILE 26
7320 #define TBEGIN 27
7321 #define TEND 28
7322 typedef smallint token_id_t;
7323
7324 /* first char is indicating which tokens mark the end of a list */
7325 static const char *const tokname_array[] = {
7326         "\1end of file",
7327         "\0newline",
7328         "\0redirection",
7329         "\0word",
7330         "\0;",
7331         "\0&",
7332         "\0&&",
7333         "\0||",
7334         "\0|",
7335         "\0(",
7336         "\1)",
7337         "\1;;",
7338         "\1`",
7339 #define KWDOFFSET 13
7340         /* the following are keywords */
7341         "\0!",
7342         "\0case",
7343         "\1do",
7344         "\1done",
7345         "\1elif",
7346         "\1else",
7347         "\1esac",
7348         "\1fi",
7349         "\0for",
7350         "\0if",
7351         "\0in",
7352         "\1then",
7353         "\0until",
7354         "\0while",
7355         "\0{",
7356         "\1}",
7357 };
7358
7359 static const char *
7360 tokname(int tok)
7361 {
7362         static char buf[16];
7363
7364 //try this:
7365 //if (tok < TSEMI) return tokname_array[tok] + 1;
7366 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7367 //return buf;
7368
7369         if (tok >= TSEMI)
7370                 buf[0] = '"';
7371         sprintf(buf + (tok >= TSEMI), "%s%c",
7372                         tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7373         return buf;
7374 }
7375
7376 /* Wrapper around strcmp for qsort/bsearch/... */
7377 static int
7378 pstrcmp(const void *a, const void *b)
7379 {
7380         return strcmp((char*) a, (*(char**) b) + 1);
7381 }
7382
7383 static const char *const *
7384 findkwd(const char *s)
7385 {
7386         return bsearch(s, tokname_array + KWDOFFSET,
7387                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
7388                         sizeof(tokname_array[0]), pstrcmp);
7389 }
7390
7391 /*
7392  * Locate and print what a word is...
7393  */
7394 static int
7395 describe_command(char *command, int describe_command_verbose)
7396 {
7397         struct cmdentry entry;
7398         struct tblentry *cmdp;
7399 #if ENABLE_ASH_ALIAS
7400         const struct alias *ap;
7401 #endif
7402         const char *path = pathval();
7403
7404         if (describe_command_verbose) {
7405                 out1str(command);
7406         }
7407
7408         /* First look at the keywords */
7409         if (findkwd(command)) {
7410                 out1str(describe_command_verbose ? " is a shell keyword" : command);
7411                 goto out;
7412         }
7413
7414 #if ENABLE_ASH_ALIAS
7415         /* Then look at the aliases */
7416         ap = lookupalias(command, 0);
7417         if (ap != NULL) {
7418                 if (!describe_command_verbose) {
7419                         out1str("alias ");
7420                         printalias(ap);
7421                         return 0;
7422                 }
7423                 out1fmt(" is an alias for %s", ap->val);
7424                 goto out;
7425         }
7426 #endif
7427         /* Then check if it is a tracked alias */
7428         cmdp = cmdlookup(command, 0);
7429         if (cmdp != NULL) {
7430                 entry.cmdtype = cmdp->cmdtype;
7431                 entry.u = cmdp->param;
7432         } else {
7433                 /* Finally use brute force */
7434                 find_command(command, &entry, DO_ABS, path);
7435         }
7436
7437         switch (entry.cmdtype) {
7438         case CMDNORMAL: {
7439                 int j = entry.u.index;
7440                 char *p;
7441                 if (j < 0) {
7442                         p = command;
7443                 } else {
7444                         do {
7445                                 p = padvance(&path, command);
7446                                 stunalloc(p);
7447                         } while (--j >= 0);
7448                 }
7449                 if (describe_command_verbose) {
7450                         out1fmt(" is%s %s",
7451                                 (cmdp ? " a tracked alias for" : nullstr), p
7452                         );
7453                 } else {
7454                         out1str(p);
7455                 }
7456                 break;
7457         }
7458
7459         case CMDFUNCTION:
7460                 if (describe_command_verbose) {
7461                         out1str(" is a shell function");
7462                 } else {
7463                         out1str(command);
7464                 }
7465                 break;
7466
7467         case CMDBUILTIN:
7468                 if (describe_command_verbose) {
7469                         out1fmt(" is a %sshell builtin",
7470                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7471                                         "special " : nullstr
7472                         );
7473                 } else {
7474                         out1str(command);
7475                 }
7476                 break;
7477
7478         default:
7479                 if (describe_command_verbose) {
7480                         out1str(": not found\n");
7481                 }
7482                 return 127;
7483         }
7484  out:
7485         outstr("\n", stdout);
7486         return 0;
7487 }
7488
7489 static int
7490 typecmd(int argc UNUSED_PARAM, char **argv)
7491 {
7492         int i = 1;
7493         int err = 0;
7494         int verbose = 1;
7495
7496         /* type -p ... ? (we don't bother checking for 'p') */
7497         if (argv[1] && argv[1][0] == '-') {
7498                 i++;
7499                 verbose = 0;
7500         }
7501         while (argv[i]) {
7502                 err |= describe_command(argv[i++], verbose);
7503         }
7504         return err;
7505 }
7506
7507 #if ENABLE_ASH_CMDCMD
7508 static int
7509 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7510 {
7511         int c;
7512         enum {
7513                 VERIFY_BRIEF = 1,
7514                 VERIFY_VERBOSE = 2,
7515         } verify = 0;
7516
7517         while ((c = nextopt("pvV")) != '\0')
7518                 if (c == 'V')
7519                         verify |= VERIFY_VERBOSE;
7520                 else if (c == 'v')
7521                         verify |= VERIFY_BRIEF;
7522 #if DEBUG
7523                 else if (c != 'p')
7524                         abort();
7525 #endif
7526         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7527         if (verify && (*argptr != NULL)) {
7528                 return describe_command(*argptr, verify - VERIFY_BRIEF);
7529         }
7530
7531         return 0;
7532 }
7533 #endif
7534
7535
7536 /* ============ eval.c */
7537
7538 static int funcblocksize;          /* size of structures in function */
7539 static int funcstringsize;         /* size of strings in node */
7540 static void *funcblock;            /* block to allocate function from */
7541 static char *funcstring;           /* block to allocate strings from */
7542
7543 /* flags in argument to evaltree */
7544 #define EV_EXIT 01              /* exit after evaluating tree */
7545 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
7546 #define EV_BACKCMD 04           /* command executing within back quotes */
7547
7548 static const short nodesize[26] = {
7549         SHELL_ALIGN(sizeof(struct ncmd)),
7550         SHELL_ALIGN(sizeof(struct npipe)),
7551         SHELL_ALIGN(sizeof(struct nredir)),
7552         SHELL_ALIGN(sizeof(struct nredir)),
7553         SHELL_ALIGN(sizeof(struct nredir)),
7554         SHELL_ALIGN(sizeof(struct nbinary)),
7555         SHELL_ALIGN(sizeof(struct nbinary)),
7556         SHELL_ALIGN(sizeof(struct nbinary)),
7557         SHELL_ALIGN(sizeof(struct nif)),
7558         SHELL_ALIGN(sizeof(struct nbinary)),
7559         SHELL_ALIGN(sizeof(struct nbinary)),
7560         SHELL_ALIGN(sizeof(struct nfor)),
7561         SHELL_ALIGN(sizeof(struct ncase)),
7562         SHELL_ALIGN(sizeof(struct nclist)),
7563         SHELL_ALIGN(sizeof(struct narg)),
7564         SHELL_ALIGN(sizeof(struct narg)),
7565         SHELL_ALIGN(sizeof(struct nfile)),
7566         SHELL_ALIGN(sizeof(struct nfile)),
7567         SHELL_ALIGN(sizeof(struct nfile)),
7568         SHELL_ALIGN(sizeof(struct nfile)),
7569         SHELL_ALIGN(sizeof(struct nfile)),
7570         SHELL_ALIGN(sizeof(struct ndup)),
7571         SHELL_ALIGN(sizeof(struct ndup)),
7572         SHELL_ALIGN(sizeof(struct nhere)),
7573         SHELL_ALIGN(sizeof(struct nhere)),
7574         SHELL_ALIGN(sizeof(struct nnot)),
7575 };
7576
7577 static void calcsize(union node *n);
7578
7579 static void
7580 sizenodelist(struct nodelist *lp)
7581 {
7582         while (lp) {
7583                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7584                 calcsize(lp->n);
7585                 lp = lp->next;
7586         }
7587 }
7588
7589 static void
7590 calcsize(union node *n)
7591 {
7592         if (n == NULL)
7593                 return;
7594         funcblocksize += nodesize[n->type];
7595         switch (n->type) {
7596         case NCMD:
7597                 calcsize(n->ncmd.redirect);
7598                 calcsize(n->ncmd.args);
7599                 calcsize(n->ncmd.assign);
7600                 break;
7601         case NPIPE:
7602                 sizenodelist(n->npipe.cmdlist);
7603                 break;
7604         case NREDIR:
7605         case NBACKGND:
7606         case NSUBSHELL:
7607                 calcsize(n->nredir.redirect);
7608                 calcsize(n->nredir.n);
7609                 break;
7610         case NAND:
7611         case NOR:
7612         case NSEMI:
7613         case NWHILE:
7614         case NUNTIL:
7615                 calcsize(n->nbinary.ch2);
7616                 calcsize(n->nbinary.ch1);
7617                 break;
7618         case NIF:
7619                 calcsize(n->nif.elsepart);
7620                 calcsize(n->nif.ifpart);
7621                 calcsize(n->nif.test);
7622                 break;
7623         case NFOR:
7624                 funcstringsize += strlen(n->nfor.var) + 1;
7625                 calcsize(n->nfor.body);
7626                 calcsize(n->nfor.args);
7627                 break;
7628         case NCASE:
7629                 calcsize(n->ncase.cases);
7630                 calcsize(n->ncase.expr);
7631                 break;
7632         case NCLIST:
7633                 calcsize(n->nclist.body);
7634                 calcsize(n->nclist.pattern);
7635                 calcsize(n->nclist.next);
7636                 break;
7637         case NDEFUN:
7638         case NARG:
7639                 sizenodelist(n->narg.backquote);
7640                 funcstringsize += strlen(n->narg.text) + 1;
7641                 calcsize(n->narg.next);
7642                 break;
7643         case NTO:
7644         case NCLOBBER:
7645         case NFROM:
7646         case NFROMTO:
7647         case NAPPEND:
7648                 calcsize(n->nfile.fname);
7649                 calcsize(n->nfile.next);
7650                 break;
7651         case NTOFD:
7652         case NFROMFD:
7653                 calcsize(n->ndup.vname);
7654                 calcsize(n->ndup.next);
7655         break;
7656         case NHERE:
7657         case NXHERE:
7658                 calcsize(n->nhere.doc);
7659                 calcsize(n->nhere.next);
7660                 break;
7661         case NNOT:
7662                 calcsize(n->nnot.com);
7663                 break;
7664         };
7665 }
7666
7667 static char *
7668 nodeckstrdup(char *s)
7669 {
7670         char *rtn = funcstring;
7671
7672         strcpy(funcstring, s);
7673         funcstring += strlen(s) + 1;
7674         return rtn;
7675 }
7676
7677 static union node *copynode(union node *);
7678
7679 static struct nodelist *
7680 copynodelist(struct nodelist *lp)
7681 {
7682         struct nodelist *start;
7683         struct nodelist **lpp;
7684
7685         lpp = &start;
7686         while (lp) {
7687                 *lpp = funcblock;
7688                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7689                 (*lpp)->n = copynode(lp->n);
7690                 lp = lp->next;
7691                 lpp = &(*lpp)->next;
7692         }
7693         *lpp = NULL;
7694         return start;
7695 }
7696
7697 static union node *
7698 copynode(union node *n)
7699 {
7700         union node *new;
7701
7702         if (n == NULL)
7703                 return NULL;
7704         new = funcblock;
7705         funcblock = (char *) funcblock + nodesize[n->type];
7706
7707         switch (n->type) {
7708         case NCMD:
7709                 new->ncmd.redirect = copynode(n->ncmd.redirect);
7710                 new->ncmd.args = copynode(n->ncmd.args);
7711                 new->ncmd.assign = copynode(n->ncmd.assign);
7712                 break;
7713         case NPIPE:
7714                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7715                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7716                 break;
7717         case NREDIR:
7718         case NBACKGND:
7719         case NSUBSHELL:
7720                 new->nredir.redirect = copynode(n->nredir.redirect);
7721                 new->nredir.n = copynode(n->nredir.n);
7722                 break;
7723         case NAND:
7724         case NOR:
7725         case NSEMI:
7726         case NWHILE:
7727         case NUNTIL:
7728                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7729                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7730                 break;
7731         case NIF:
7732                 new->nif.elsepart = copynode(n->nif.elsepart);
7733                 new->nif.ifpart = copynode(n->nif.ifpart);
7734                 new->nif.test = copynode(n->nif.test);
7735                 break;
7736         case NFOR:
7737                 new->nfor.var = nodeckstrdup(n->nfor.var);
7738                 new->nfor.body = copynode(n->nfor.body);
7739                 new->nfor.args = copynode(n->nfor.args);
7740                 break;
7741         case NCASE:
7742                 new->ncase.cases = copynode(n->ncase.cases);
7743                 new->ncase.expr = copynode(n->ncase.expr);
7744                 break;
7745         case NCLIST:
7746                 new->nclist.body = copynode(n->nclist.body);
7747                 new->nclist.pattern = copynode(n->nclist.pattern);
7748                 new->nclist.next = copynode(n->nclist.next);
7749                 break;
7750         case NDEFUN:
7751         case NARG:
7752                 new->narg.backquote = copynodelist(n->narg.backquote);
7753                 new->narg.text = nodeckstrdup(n->narg.text);
7754                 new->narg.next = copynode(n->narg.next);
7755                 break;
7756         case NTO:
7757         case NCLOBBER:
7758         case NFROM:
7759         case NFROMTO:
7760         case NAPPEND:
7761                 new->nfile.fname = copynode(n->nfile.fname);
7762                 new->nfile.fd = n->nfile.fd;
7763                 new->nfile.next = copynode(n->nfile.next);
7764                 break;
7765         case NTOFD:
7766         case NFROMFD:
7767                 new->ndup.vname = copynode(n->ndup.vname);
7768                 new->ndup.dupfd = n->ndup.dupfd;
7769                 new->ndup.fd = n->ndup.fd;
7770                 new->ndup.next = copynode(n->ndup.next);
7771                 break;
7772         case NHERE:
7773         case NXHERE:
7774                 new->nhere.doc = copynode(n->nhere.doc);
7775                 new->nhere.fd = n->nhere.fd;
7776                 new->nhere.next = copynode(n->nhere.next);
7777                 break;
7778         case NNOT:
7779                 new->nnot.com = copynode(n->nnot.com);
7780                 break;
7781         };
7782         new->type = n->type;
7783         return new;
7784 }
7785
7786 /*
7787  * Make a copy of a parse tree.
7788  */
7789 static struct funcnode *
7790 copyfunc(union node *n)
7791 {
7792         struct funcnode *f;
7793         size_t blocksize;
7794
7795         funcblocksize = offsetof(struct funcnode, n);
7796         funcstringsize = 0;
7797         calcsize(n);
7798         blocksize = funcblocksize;
7799         f = ckmalloc(blocksize + funcstringsize);
7800         funcblock = (char *) f + offsetof(struct funcnode, n);
7801         funcstring = (char *) f + blocksize;
7802         copynode(n);
7803         f->count = 0;
7804         return f;
7805 }
7806
7807 /*
7808  * Define a shell function.
7809  */
7810 static void
7811 defun(char *name, union node *func)
7812 {
7813         struct cmdentry entry;
7814
7815         INT_OFF;
7816         entry.cmdtype = CMDFUNCTION;
7817         entry.u.func = copyfunc(func);
7818         addcmdentry(name, &entry);
7819         INT_ON;
7820 }
7821
7822 static int evalskip;            /* set if we are skipping commands */
7823 /* reasons for skipping commands (see comment on breakcmd routine) */
7824 #define SKIPBREAK      (1 << 0)
7825 #define SKIPCONT       (1 << 1)
7826 #define SKIPFUNC       (1 << 2)
7827 #define SKIPFILE       (1 << 3)
7828 #define SKIPEVAL       (1 << 4)
7829 static int skipcount;           /* number of levels to skip */
7830 static int funcnest;            /* depth of function calls */
7831 static int loopnest;            /* current loop nesting level */
7832
7833 /* forward decl way out to parsing code - dotrap needs it */
7834 static int evalstring(char *s, int mask);
7835
7836 /*
7837  * Called to execute a trap.  Perhaps we should avoid entering new trap
7838  * handlers while we are executing a trap handler.
7839  */
7840 static int
7841 dotrap(void)
7842 {
7843         char *p;
7844         char *q;
7845         int i;
7846         int savestatus;
7847         int skip;
7848
7849         savestatus = exitstatus;
7850         pendingsig = 0;
7851         xbarrier();
7852
7853         for (i = 1, q = gotsig; i < NSIG; i++, q++) {
7854                 if (!*q)
7855                         continue;
7856                 *q = '\0';
7857
7858                 p = trap[i];
7859                 if (!p)
7860                         continue;
7861                 skip = evalstring(p, SKIPEVAL);
7862                 exitstatus = savestatus;
7863                 if (skip)
7864                         return skip;
7865         }
7866
7867         return 0;
7868 }
7869
7870 /* forward declarations - evaluation is fairly recursive business... */
7871 static void evalloop(union node *, int);
7872 static void evalfor(union node *, int);
7873 static void evalcase(union node *, int);
7874 static void evalsubshell(union node *, int);
7875 static void expredir(union node *);
7876 static void evalpipe(union node *, int);
7877 static void evalcommand(union node *, int);
7878 static int evalbltin(const struct builtincmd *, int, char **);
7879 static void prehash(union node *);
7880
7881 /*
7882  * Evaluate a parse tree.  The value is left in the global variable
7883  * exitstatus.
7884  */
7885 static void
7886 evaltree(union node *n, int flags)
7887 {
7888
7889         struct jmploc *volatile savehandler = exception_handler;
7890         struct jmploc jmploc;
7891         int checkexit = 0;
7892         void (*evalfn)(union node *, int);
7893         int status;
7894
7895         if (n == NULL) {
7896                 TRACE(("evaltree(NULL) called\n"));
7897                 goto out1;
7898         }
7899         TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7900                         getpid(), n, n->type, flags));
7901
7902         exception_handler = &jmploc;
7903         {
7904                 int err = setjmp(jmploc.loc);
7905                 if (err) {
7906                         /* if it was a signal, check for trap handlers */
7907                         if (exception == EXSIG)
7908                                 goto out;
7909                         /* continue on the way out */
7910                         exception_handler = savehandler;
7911                         longjmp(exception_handler->loc, err);
7912                 }
7913         }
7914
7915         switch (n->type) {
7916         default:
7917 #if DEBUG
7918                 out1fmt("Node type = %d\n", n->type);
7919                 fflush(stdout);
7920                 break;
7921 #endif
7922         case NNOT:
7923                 evaltree(n->nnot.com, EV_TESTED);
7924                 status = !exitstatus;
7925                 goto setstatus;
7926         case NREDIR:
7927                 expredir(n->nredir.redirect);
7928                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7929                 if (!status) {
7930                         evaltree(n->nredir.n, flags & EV_TESTED);
7931                         status = exitstatus;
7932                 }
7933                 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
7934                 goto setstatus;
7935         case NCMD:
7936                 evalfn = evalcommand;
7937  checkexit:
7938                 if (eflag && !(flags & EV_TESTED))
7939                         checkexit = ~0;
7940                 goto calleval;
7941         case NFOR:
7942                 evalfn = evalfor;
7943                 goto calleval;
7944         case NWHILE:
7945         case NUNTIL:
7946                 evalfn = evalloop;
7947                 goto calleval;
7948         case NSUBSHELL:
7949         case NBACKGND:
7950                 evalfn = evalsubshell;
7951                 goto calleval;
7952         case NPIPE:
7953                 evalfn = evalpipe;
7954                 goto checkexit;
7955         case NCASE:
7956                 evalfn = evalcase;
7957                 goto calleval;
7958         case NAND:
7959         case NOR:
7960         case NSEMI: {
7961
7962 #if NAND + 1 != NOR
7963 #error NAND + 1 != NOR
7964 #endif
7965 #if NOR + 1 != NSEMI
7966 #error NOR + 1 != NSEMI
7967 #endif
7968                 unsigned is_or = n->type - NAND;
7969                 evaltree(
7970                         n->nbinary.ch1,
7971                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
7972                 );
7973                 if (!exitstatus == is_or)
7974                         break;
7975                 if (!evalskip) {
7976                         n = n->nbinary.ch2;
7977  evaln:
7978                         evalfn = evaltree;
7979  calleval:
7980                         evalfn(n, flags);
7981                         break;
7982                 }
7983                 break;
7984         }
7985         case NIF:
7986                 evaltree(n->nif.test, EV_TESTED);
7987                 if (evalskip)
7988                         break;
7989                 if (exitstatus == 0) {
7990                         n = n->nif.ifpart;
7991                         goto evaln;
7992                 } else if (n->nif.elsepart) {
7993                         n = n->nif.elsepart;
7994                         goto evaln;
7995                 }
7996                 goto success;
7997         case NDEFUN:
7998                 defun(n->narg.text, n->narg.next);
7999  success:
8000                 status = 0;
8001  setstatus:
8002                 exitstatus = status;
8003                 break;
8004         }
8005
8006  out:
8007         exception_handler = savehandler;
8008  out1:
8009         if (checkexit & exitstatus)
8010                 evalskip |= SKIPEVAL;
8011         else if (pendingsig && dotrap())
8012                 goto exexit;
8013
8014         if (flags & EV_EXIT) {
8015  exexit:
8016                 raise_exception(EXEXIT);
8017         }
8018 }
8019
8020 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8021 static
8022 #endif
8023 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8024
8025 static void
8026 evalloop(union node *n, int flags)
8027 {
8028         int status;
8029
8030         loopnest++;
8031         status = 0;
8032         flags &= EV_TESTED;
8033         for (;;) {
8034                 int i;
8035
8036                 evaltree(n->nbinary.ch1, EV_TESTED);
8037                 if (evalskip) {
8038  skipping:
8039                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8040                                 evalskip = 0;
8041                                 continue;
8042                         }
8043                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8044                                 evalskip = 0;
8045                         break;
8046                 }
8047                 i = exitstatus;
8048                 if (n->type != NWHILE)
8049                         i = !i;
8050                 if (i != 0)
8051                         break;
8052                 evaltree(n->nbinary.ch2, flags);
8053                 status = exitstatus;
8054                 if (evalskip)
8055                         goto skipping;
8056         }
8057         loopnest--;
8058         exitstatus = status;
8059 }
8060
8061 static void
8062 evalfor(union node *n, int flags)
8063 {
8064         struct arglist arglist;
8065         union node *argp;
8066         struct strlist *sp;
8067         struct stackmark smark;
8068
8069         setstackmark(&smark);
8070         arglist.list = NULL;
8071         arglist.lastp = &arglist.list;
8072         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8073                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8074                 /* XXX */
8075                 if (evalskip)
8076                         goto out;
8077         }
8078         *arglist.lastp = NULL;
8079
8080         exitstatus = 0;
8081         loopnest++;
8082         flags &= EV_TESTED;
8083         for (sp = arglist.list; sp; sp = sp->next) {
8084                 setvar(n->nfor.var, sp->text, 0);
8085                 evaltree(n->nfor.body, flags);
8086                 if (evalskip) {
8087                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8088                                 evalskip = 0;
8089                                 continue;
8090                         }
8091                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8092                                 evalskip = 0;
8093                         break;
8094                 }
8095         }
8096         loopnest--;
8097  out:
8098         popstackmark(&smark);
8099 }
8100
8101 static void
8102 evalcase(union node *n, int flags)
8103 {
8104         union node *cp;
8105         union node *patp;
8106         struct arglist arglist;
8107         struct stackmark smark;
8108
8109         setstackmark(&smark);
8110         arglist.list = NULL;
8111         arglist.lastp = &arglist.list;
8112         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8113         exitstatus = 0;
8114         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8115                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8116                         if (casematch(patp, arglist.list->text)) {
8117                                 if (evalskip == 0) {
8118                                         evaltree(cp->nclist.body, flags);
8119                                 }
8120                                 goto out;
8121                         }
8122                 }
8123         }
8124  out:
8125         popstackmark(&smark);
8126 }
8127
8128 /*
8129  * Kick off a subshell to evaluate a tree.
8130  */
8131 static void
8132 evalsubshell(union node *n, int flags)
8133 {
8134         struct job *jp;
8135         int backgnd = (n->type == NBACKGND);
8136         int status;
8137
8138         expredir(n->nredir.redirect);
8139         if (!backgnd && flags & EV_EXIT && !trap[0])
8140                 goto nofork;
8141         INT_OFF;
8142         jp = makejob(/*n,*/ 1);
8143         if (forkshell(jp, n, backgnd) == 0) {
8144                 INT_ON;
8145                 flags |= EV_EXIT;
8146                 if (backgnd)
8147                         flags &=~ EV_TESTED;
8148  nofork:
8149                 redirect(n->nredir.redirect, 0);
8150                 evaltreenr(n->nredir.n, flags);
8151                 /* never returns */
8152         }
8153         status = 0;
8154         if (!backgnd)
8155                 status = waitforjob(jp);
8156         exitstatus = status;
8157         INT_ON;
8158 }
8159
8160 /*
8161  * Compute the names of the files in a redirection list.
8162  */
8163 static void fixredir(union node *, const char *, int);
8164 static void
8165 expredir(union node *n)
8166 {
8167         union node *redir;
8168
8169         for (redir = n; redir; redir = redir->nfile.next) {
8170                 struct arglist fn;
8171
8172                 fn.list = NULL;
8173                 fn.lastp = &fn.list;
8174                 switch (redir->type) {
8175                 case NFROMTO:
8176                 case NFROM:
8177                 case NTO:
8178                 case NCLOBBER:
8179                 case NAPPEND:
8180                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8181                         redir->nfile.expfname = fn.list->text;
8182                         break;
8183                 case NFROMFD:
8184                 case NTOFD:
8185                         if (redir->ndup.vname) {
8186                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8187                                 if (fn.list == NULL)
8188                                         ash_msg_and_raise_error("redir error");
8189                                 fixredir(redir, fn.list->text, 1);
8190                         }
8191                         break;
8192                 }
8193         }
8194 }
8195
8196 /*
8197  * Evaluate a pipeline.  All the processes in the pipeline are children
8198  * of the process creating the pipeline.  (This differs from some versions
8199  * of the shell, which make the last process in a pipeline the parent
8200  * of all the rest.)
8201  */
8202 static void
8203 evalpipe(union node *n, int flags)
8204 {
8205         struct job *jp;
8206         struct nodelist *lp;
8207         int pipelen;
8208         int prevfd;
8209         int pip[2];
8210
8211         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8212         pipelen = 0;
8213         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8214                 pipelen++;
8215         flags |= EV_EXIT;
8216         INT_OFF;
8217         jp = makejob(/*n,*/ pipelen);
8218         prevfd = -1;
8219         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8220                 prehash(lp->n);
8221                 pip[1] = -1;
8222                 if (lp->next) {
8223                         if (pipe(pip) < 0) {
8224                                 close(prevfd);
8225                                 ash_msg_and_raise_error("pipe call failed");
8226                         }
8227                 }
8228                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8229                         INT_ON;
8230                         if (pip[1] >= 0) {
8231                                 close(pip[0]);
8232                         }
8233                         if (prevfd > 0) {
8234                                 dup2(prevfd, 0);
8235                                 close(prevfd);
8236                         }
8237                         if (pip[1] > 1) {
8238                                 dup2(pip[1], 1);
8239                                 close(pip[1]);
8240                         }
8241                         evaltreenr(lp->n, flags);
8242                         /* never returns */
8243                 }
8244                 if (prevfd >= 0)
8245                         close(prevfd);
8246                 prevfd = pip[0];
8247                 close(pip[1]);
8248         }
8249         if (n->npipe.pipe_backgnd == 0) {
8250                 exitstatus = waitforjob(jp);
8251                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
8252         }
8253         INT_ON;
8254 }
8255
8256 /*
8257  * Controls whether the shell is interactive or not.
8258  */
8259 static void
8260 setinteractive(int on)
8261 {
8262         static smallint is_interactive;
8263
8264         if (++on == is_interactive)
8265                 return;
8266         is_interactive = on;
8267         setsignal(SIGINT);
8268         setsignal(SIGQUIT);
8269         setsignal(SIGTERM);
8270 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8271         if (is_interactive > 1) {
8272                 /* Looks like they want an interactive shell */
8273                 static smallint did_banner;
8274
8275                 if (!did_banner) {
8276                         out1fmt(
8277                                 "\n\n"
8278                                 "%s built-in shell (ash)\n"
8279                                 "Enter 'help' for a list of built-in commands."
8280                                 "\n\n",
8281                                 bb_banner);
8282                         did_banner = 1;
8283                 }
8284         }
8285 #endif
8286 }
8287
8288 static void
8289 optschanged(void)
8290 {
8291 #if DEBUG
8292         opentrace();
8293 #endif
8294         setinteractive(iflag);
8295         setjobctl(mflag);
8296 #if ENABLE_FEATURE_EDITING_VI
8297         if (viflag)
8298                 line_input_state->flags |= VI_MODE;
8299         else
8300                 line_input_state->flags &= ~VI_MODE;
8301 #else
8302         viflag = 0; /* forcibly keep the option off */
8303 #endif
8304 }
8305
8306 static struct localvar *localvars;
8307
8308 /*
8309  * Called after a function returns.
8310  * Interrupts must be off.
8311  */
8312 static void
8313 poplocalvars(void)
8314 {
8315         struct localvar *lvp;
8316         struct var *vp;
8317
8318         while ((lvp = localvars) != NULL) {
8319                 localvars = lvp->next;
8320                 vp = lvp->vp;
8321                 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8322                 if (vp == NULL) {       /* $- saved */
8323                         memcpy(optlist, lvp->text, sizeof(optlist));
8324                         free((char*)lvp->text);
8325                         optschanged();
8326                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8327                         unsetvar(vp->text);
8328                 } else {
8329                         if (vp->func)
8330                                 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8331                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8332                                 free((char*)vp->text);
8333                         vp->flags = lvp->flags;
8334                         vp->text = lvp->text;
8335                 }
8336                 free(lvp);
8337         }
8338 }
8339
8340 static int
8341 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8342 {
8343         volatile struct shparam saveparam;
8344         struct localvar *volatile savelocalvars;
8345         struct jmploc *volatile savehandler;
8346         struct jmploc jmploc;
8347         int e;
8348
8349         saveparam = shellparam;
8350         savelocalvars = localvars;
8351         e = setjmp(jmploc.loc);
8352         if (e) {
8353                 goto funcdone;
8354         }
8355         INT_OFF;
8356         savehandler = exception_handler;
8357         exception_handler = &jmploc;
8358         localvars = NULL;
8359         shellparam.malloced = 0;
8360         func->count++;
8361         funcnest++;
8362         INT_ON;
8363         shellparam.nparam = argc - 1;
8364         shellparam.p = argv + 1;
8365 #if ENABLE_ASH_GETOPTS
8366         shellparam.optind = 1;
8367         shellparam.optoff = -1;
8368 #endif
8369         evaltree(&func->n, flags & EV_TESTED);
8370  funcdone:
8371         INT_OFF;
8372         funcnest--;
8373         freefunc(func);
8374         poplocalvars();
8375         localvars = savelocalvars;
8376         freeparam(&shellparam);
8377         shellparam = saveparam;
8378         exception_handler = savehandler;
8379         INT_ON;
8380         evalskip &= ~SKIPFUNC;
8381         return e;
8382 }
8383
8384 #if ENABLE_ASH_CMDCMD
8385 static char **
8386 parse_command_args(char **argv, const char **path)
8387 {
8388         char *cp, c;
8389
8390         for (;;) {
8391                 cp = *++argv;
8392                 if (!cp)
8393                         return 0;
8394                 if (*cp++ != '-')
8395                         break;
8396                 c = *cp++;
8397                 if (!c)
8398                         break;
8399                 if (c == '-' && !*cp) {
8400                         argv++;
8401                         break;
8402                 }
8403                 do {
8404                         switch (c) {
8405                         case 'p':
8406                                 *path = bb_default_path;
8407                                 break;
8408                         default:
8409                                 /* run 'typecmd' for other options */
8410                                 return 0;
8411                         }
8412                         c = *cp++;
8413                 } while (c);
8414         }
8415         return argv;
8416 }
8417 #endif
8418
8419 /*
8420  * Make a variable a local variable.  When a variable is made local, it's
8421  * value and flags are saved in a localvar structure.  The saved values
8422  * will be restored when the shell function returns.  We handle the name
8423  * "-" as a special case.
8424  */
8425 static void
8426 mklocal(char *name)
8427 {
8428         struct localvar *lvp;
8429         struct var **vpp;
8430         struct var *vp;
8431
8432         INT_OFF;
8433         lvp = ckzalloc(sizeof(struct localvar));
8434         if (LONE_DASH(name)) {
8435                 char *p;
8436                 p = ckmalloc(sizeof(optlist));
8437                 lvp->text = memcpy(p, optlist, sizeof(optlist));
8438                 vp = NULL;
8439         } else {
8440                 char *eq;
8441
8442                 vpp = hashvar(name);
8443                 vp = *findvar(vpp, name);
8444                 eq = strchr(name, '=');
8445                 if (vp == NULL) {
8446                         if (eq)
8447                                 setvareq(name, VSTRFIXED);
8448                         else
8449                                 setvar(name, NULL, VSTRFIXED);
8450                         vp = *vpp;      /* the new variable */
8451                         lvp->flags = VUNSET;
8452                 } else {
8453                         lvp->text = vp->text;
8454                         lvp->flags = vp->flags;
8455                         vp->flags |= VSTRFIXED|VTEXTFIXED;
8456                         if (eq)
8457                                 setvareq(name, 0);
8458                 }
8459         }
8460         lvp->vp = vp;
8461         lvp->next = localvars;
8462         localvars = lvp;
8463         INT_ON;
8464 }
8465
8466 /*
8467  * The "local" command.
8468  */
8469 static int
8470 localcmd(int argc UNUSED_PARAM, char **argv)
8471 {
8472         char *name;
8473
8474         argv = argptr;
8475         while ((name = *argv++) != NULL) {
8476                 mklocal(name);
8477         }
8478         return 0;
8479 }
8480
8481 static int
8482 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8483 {
8484         return 1;
8485 }
8486
8487 static int
8488 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8489 {
8490         return 0;
8491 }
8492
8493 static int
8494 execcmd(int argc UNUSED_PARAM, char **argv)
8495 {
8496         if (argv[1]) {
8497                 iflag = 0;              /* exit on error */
8498                 mflag = 0;
8499                 optschanged();
8500                 shellexec(argv + 1, pathval(), 0);
8501         }
8502         return 0;
8503 }
8504
8505 /*
8506  * The return command.
8507  */
8508 static int
8509 returncmd(int argc UNUSED_PARAM, char **argv)
8510 {
8511         /*
8512          * If called outside a function, do what ksh does;
8513          * skip the rest of the file.
8514          */
8515         evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8516         return argv[1] ? number(argv[1]) : exitstatus;
8517 }
8518
8519 /* Forward declarations for builtintab[] */
8520 static int breakcmd(int, char **);
8521 static int dotcmd(int, char **);
8522 static int evalcmd(int, char **);
8523 static int exitcmd(int, char **);
8524 static int exportcmd(int, char **);
8525 #if ENABLE_ASH_GETOPTS
8526 static int getoptscmd(int, char **);
8527 #endif
8528 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8529 static int helpcmd(int, char **);
8530 #endif
8531 #if ENABLE_ASH_MATH_SUPPORT
8532 static int letcmd(int, char **);
8533 #endif
8534 static int readcmd(int, char **);
8535 static int setcmd(int, char **);
8536 static int shiftcmd(int, char **);
8537 static int timescmd(int, char **);
8538 static int trapcmd(int, char **);
8539 static int umaskcmd(int, char **);
8540 static int unsetcmd(int, char **);
8541 static int ulimitcmd(int, char **);
8542
8543 #define BUILTIN_NOSPEC          "0"
8544 #define BUILTIN_SPECIAL         "1"
8545 #define BUILTIN_REGULAR         "2"
8546 #define BUILTIN_SPEC_REG        "3"
8547 #define BUILTIN_ASSIGN          "4"
8548 #define BUILTIN_SPEC_ASSG       "5"
8549 #define BUILTIN_REG_ASSG        "6"
8550 #define BUILTIN_SPEC_REG_ASSG   "7"
8551
8552 /* We do not handle [[ expr ]] bashism bash-compatibly,
8553  * we make it a synonym of [ expr ].
8554  * Basically, word splitting and pathname expansion should NOT be performed
8555  * Examples:
8556  * no word splitting:     a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8557  * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8558  * Additional operators:
8559  * || and && should work as -o and -a
8560  * =~ regexp match
8561  * Apart from the above, [[ expr ]] should work as [ expr ]
8562  */
8563
8564 #define echocmd   echo_main
8565 #define printfcmd printf_main
8566 #define testcmd   test_main
8567
8568 /* Keep these in proper order since it is searched via bsearch() */
8569 static const struct builtincmd builtintab[] = {
8570         { BUILTIN_SPEC_REG      ".", dotcmd },
8571         { BUILTIN_SPEC_REG      ":", truecmd },
8572 #if ENABLE_ASH_BUILTIN_TEST
8573         { BUILTIN_REGULAR       "[", testcmd },
8574 #if ENABLE_ASH_BASH_COMPAT
8575         { BUILTIN_REGULAR       "[[", testcmd },
8576 #endif
8577 #endif
8578 #if ENABLE_ASH_ALIAS
8579         { BUILTIN_REG_ASSG      "alias", aliascmd },
8580 #endif
8581 #if JOBS
8582         { BUILTIN_REGULAR       "bg", fg_bgcmd },
8583 #endif
8584         { BUILTIN_SPEC_REG      "break", breakcmd },
8585         { BUILTIN_REGULAR       "cd", cdcmd },
8586         { BUILTIN_NOSPEC        "chdir", cdcmd },
8587 #if ENABLE_ASH_CMDCMD
8588         { BUILTIN_REGULAR       "command", commandcmd },
8589 #endif
8590         { BUILTIN_SPEC_REG      "continue", breakcmd },
8591 #if ENABLE_ASH_BUILTIN_ECHO
8592         { BUILTIN_REGULAR       "echo", echocmd },
8593 #endif
8594         { BUILTIN_SPEC_REG      "eval", evalcmd },
8595         { BUILTIN_SPEC_REG      "exec", execcmd },
8596         { BUILTIN_SPEC_REG      "exit", exitcmd },
8597         { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8598         { BUILTIN_REGULAR       "false", falsecmd },
8599 #if JOBS
8600         { BUILTIN_REGULAR       "fg", fg_bgcmd },
8601 #endif
8602 #if ENABLE_ASH_GETOPTS
8603         { BUILTIN_REGULAR       "getopts", getoptscmd },
8604 #endif
8605         { BUILTIN_NOSPEC        "hash", hashcmd },
8606 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8607         { BUILTIN_NOSPEC        "help", helpcmd },
8608 #endif
8609 #if JOBS
8610         { BUILTIN_REGULAR       "jobs", jobscmd },
8611         { BUILTIN_REGULAR       "kill", killcmd },
8612 #endif
8613 #if ENABLE_ASH_MATH_SUPPORT
8614         { BUILTIN_NOSPEC        "let", letcmd },
8615 #endif
8616         { BUILTIN_ASSIGN        "local", localcmd },
8617 #if ENABLE_ASH_BUILTIN_PRINTF
8618         { BUILTIN_REGULAR       "printf", printfcmd },
8619 #endif
8620         { BUILTIN_NOSPEC        "pwd", pwdcmd },
8621         { BUILTIN_REGULAR       "read", readcmd },
8622         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8623         { BUILTIN_SPEC_REG      "return", returncmd },
8624         { BUILTIN_SPEC_REG      "set", setcmd },
8625         { BUILTIN_SPEC_REG      "shift", shiftcmd },
8626         { BUILTIN_SPEC_REG      "source", dotcmd },
8627 #if ENABLE_ASH_BUILTIN_TEST
8628         { BUILTIN_REGULAR       "test", testcmd },
8629 #endif
8630         { BUILTIN_SPEC_REG      "times", timescmd },
8631         { BUILTIN_SPEC_REG      "trap", trapcmd },
8632         { BUILTIN_REGULAR       "true", truecmd },
8633         { BUILTIN_NOSPEC        "type", typecmd },
8634         { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
8635         { BUILTIN_REGULAR       "umask", umaskcmd },
8636 #if ENABLE_ASH_ALIAS
8637         { BUILTIN_REGULAR       "unalias", unaliascmd },
8638 #endif
8639         { BUILTIN_SPEC_REG      "unset", unsetcmd },
8640         { BUILTIN_REGULAR       "wait", waitcmd },
8641 };
8642
8643 /* Should match the above table! */
8644 #define COMMANDCMD (builtintab + \
8645         2 + \
8646         1 * ENABLE_ASH_BUILTIN_TEST + \
8647         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8648         1 * ENABLE_ASH_ALIAS + \
8649         1 * ENABLE_ASH_JOB_CONTROL + \
8650         3)
8651 #define EXECCMD (builtintab + \
8652         2 + \
8653         1 * ENABLE_ASH_BUILTIN_TEST + \
8654         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8655         1 * ENABLE_ASH_ALIAS + \
8656         1 * ENABLE_ASH_JOB_CONTROL + \
8657         3 + \
8658         1 * ENABLE_ASH_CMDCMD + \
8659         1 + \
8660         ENABLE_ASH_BUILTIN_ECHO + \
8661         1)
8662
8663 /*
8664  * Search the table of builtin commands.
8665  */
8666 static struct builtincmd *
8667 find_builtin(const char *name)
8668 {
8669         struct builtincmd *bp;
8670
8671         bp = bsearch(
8672                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8673                 pstrcmp
8674         );
8675         return bp;
8676 }
8677
8678 /*
8679  * Execute a simple command.
8680  */
8681 static int
8682 isassignment(const char *p)
8683 {
8684         const char *q = endofname(p);
8685         if (p == q)
8686                 return 0;
8687         return *q == '=';
8688 }
8689 static int
8690 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8691 {
8692         /* Preserve exitstatus of a previous possible redirection
8693          * as POSIX mandates */
8694         return back_exitstatus;
8695 }
8696 static void
8697 evalcommand(union node *cmd, int flags)
8698 {
8699         static const struct builtincmd null_bltin = {
8700                 "\0\0", bltincmd /* why three NULs? */
8701         };
8702         struct stackmark smark;
8703         union node *argp;
8704         struct arglist arglist;
8705         struct arglist varlist;
8706         char **argv;
8707         int argc;
8708         const struct strlist *sp;
8709         struct cmdentry cmdentry;
8710         struct job *jp;
8711         char *lastarg;
8712         const char *path;
8713         int spclbltin;
8714         int status;
8715         char **nargv;
8716         struct builtincmd *bcmd;
8717         smallint cmd_is_exec;
8718         smallint pseudovarflag = 0;
8719
8720         /* First expand the arguments. */
8721         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8722         setstackmark(&smark);
8723         back_exitstatus = 0;
8724
8725         cmdentry.cmdtype = CMDBUILTIN;
8726         cmdentry.u.cmd = &null_bltin;
8727         varlist.lastp = &varlist.list;
8728         *varlist.lastp = NULL;
8729         arglist.lastp = &arglist.list;
8730         *arglist.lastp = NULL;
8731
8732         argc = 0;
8733         if (cmd->ncmd.args) {
8734                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8735                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8736         }
8737
8738         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8739                 struct strlist **spp;
8740
8741                 spp = arglist.lastp;
8742                 if (pseudovarflag && isassignment(argp->narg.text))
8743                         expandarg(argp, &arglist, EXP_VARTILDE);
8744                 else
8745                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8746
8747                 for (sp = *spp; sp; sp = sp->next)
8748                         argc++;
8749         }
8750
8751         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8752         for (sp = arglist.list; sp; sp = sp->next) {
8753                 TRACE(("evalcommand arg: %s\n", sp->text));
8754                 *nargv++ = sp->text;
8755         }
8756         *nargv = NULL;
8757
8758         lastarg = NULL;
8759         if (iflag && funcnest == 0 && argc > 0)
8760                 lastarg = nargv[-1];
8761
8762         preverrout_fd = 2;
8763         expredir(cmd->ncmd.redirect);
8764         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8765
8766         path = vpath.text;
8767         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8768                 struct strlist **spp;
8769                 char *p;
8770
8771                 spp = varlist.lastp;
8772                 expandarg(argp, &varlist, EXP_VARTILDE);
8773
8774                 /*
8775                  * Modify the command lookup path, if a PATH= assignment
8776                  * is present
8777                  */
8778                 p = (*spp)->text;
8779                 if (varequal(p, path))
8780                         path = p;
8781         }
8782
8783         /* Print the command if xflag is set. */
8784         if (xflag) {
8785                 int n;
8786                 const char *p = " %s";
8787
8788                 p++;
8789                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8790
8791                 sp = varlist.list;
8792                 for (n = 0; n < 2; n++) {
8793                         while (sp) {
8794                                 fdprintf(preverrout_fd, p, sp->text);
8795                                 sp = sp->next;
8796                                 if (*p == '%') {
8797                                         p--;
8798                                 }
8799                         }
8800                         sp = arglist.list;
8801                 }
8802                 safe_write(preverrout_fd, "\n", 1);
8803         }
8804
8805         cmd_is_exec = 0;
8806         spclbltin = -1;
8807
8808         /* Now locate the command. */
8809         if (argc) {
8810                 const char *oldpath;
8811                 int cmd_flag = DO_ERR;
8812
8813                 path += 5;
8814                 oldpath = path;
8815                 for (;;) {
8816                         find_command(argv[0], &cmdentry, cmd_flag, path);
8817                         if (cmdentry.cmdtype == CMDUNKNOWN) {
8818                                 flush_stderr();
8819                                 status = 127;
8820                                 goto bail;
8821                         }
8822
8823                         /* implement bltin and command here */
8824                         if (cmdentry.cmdtype != CMDBUILTIN)
8825                                 break;
8826                         if (spclbltin < 0)
8827                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8828                         if (cmdentry.u.cmd == EXECCMD)
8829                                 cmd_is_exec = 1;
8830 #if ENABLE_ASH_CMDCMD
8831                         if (cmdentry.u.cmd == COMMANDCMD) {
8832                                 path = oldpath;
8833                                 nargv = parse_command_args(argv, &path);
8834                                 if (!nargv)
8835                                         break;
8836                                 argc -= nargv - argv;
8837                                 argv = nargv;
8838                                 cmd_flag |= DO_NOFUNC;
8839                         } else
8840 #endif
8841                                 break;
8842                 }
8843         }
8844
8845         if (status) {
8846                 /* We have a redirection error. */
8847                 if (spclbltin > 0)
8848                         raise_exception(EXERROR);
8849  bail:
8850                 exitstatus = status;
8851                 goto out;
8852         }
8853
8854         /* Execute the command. */
8855         switch (cmdentry.cmdtype) {
8856         default:
8857 #if ENABLE_FEATURE_SH_NOFORK
8858         {
8859                 /* find_command() encodes applet_no as (-2 - applet_no) */
8860                 int applet_no = (- cmdentry.u.index - 2);
8861                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8862                         listsetvar(varlist.list, VEXPORT|VSTACK);
8863                         /* run <applet>_main() */
8864                         exitstatus = run_nofork_applet(applet_no, argv);
8865                         break;
8866                 }
8867         }
8868 #endif
8869
8870                 /* Fork off a child process if necessary. */
8871                 if (!(flags & EV_EXIT) || trap[0]) {
8872                         INT_OFF;
8873                         jp = makejob(/*cmd,*/ 1);
8874                         if (forkshell(jp, cmd, FORK_FG) != 0) {
8875                                 exitstatus = waitforjob(jp);
8876                                 INT_ON;
8877                                 break;
8878                         }
8879                         FORCE_INT_ON;
8880                 }
8881                 listsetvar(varlist.list, VEXPORT|VSTACK);
8882                 shellexec(argv, path, cmdentry.u.index);
8883                 /* NOTREACHED */
8884
8885         case CMDBUILTIN:
8886                 cmdenviron = varlist.list;
8887                 if (cmdenviron) {
8888                         struct strlist *list = cmdenviron;
8889                         int i = VNOSET;
8890                         if (spclbltin > 0 || argc == 0) {
8891                                 i = 0;
8892                                 if (cmd_is_exec && argc > 1)
8893                                         i = VEXPORT;
8894                         }
8895                         listsetvar(list, i);
8896                 }
8897                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8898                         int exit_status;
8899                         int i = exception;
8900                         if (i == EXEXIT)
8901                                 goto raise;
8902                         exit_status = 2;
8903                         if (i == EXINT)
8904                                 exit_status = 128 + SIGINT;
8905                         if (i == EXSIG)
8906                                 exit_status = 128 + pendingsig;
8907                         exitstatus = exit_status;
8908                         if (i == EXINT || spclbltin > 0) {
8909  raise:
8910                                 longjmp(exception_handler->loc, 1);
8911                         }
8912                         FORCE_INT_ON;
8913                 }
8914                 break;
8915
8916         case CMDFUNCTION:
8917                 listsetvar(varlist.list, 0);
8918                 if (evalfun(cmdentry.u.func, argc, argv, flags))
8919                         goto raise;
8920                 break;
8921         }
8922
8923  out:
8924         popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
8925         if (lastarg) {
8926                 /* dsl: I think this is intended to be used to support
8927                  * '_' in 'vi' command mode during line editing...
8928                  * However I implemented that within libedit itself.
8929                  */
8930                 setvar("_", lastarg, 0);
8931         }
8932         popstackmark(&smark);
8933 }
8934
8935 static int
8936 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8937 {
8938         char *volatile savecmdname;
8939         struct jmploc *volatile savehandler;
8940         struct jmploc jmploc;
8941         int i;
8942
8943         savecmdname = commandname;
8944         i = setjmp(jmploc.loc);
8945         if (i)
8946                 goto cmddone;
8947         savehandler = exception_handler;
8948         exception_handler = &jmploc;
8949         commandname = argv[0];
8950         argptr = argv + 1;
8951         optptr = NULL;                  /* initialize nextopt */
8952         exitstatus = (*cmd->builtin)(argc, argv);
8953         flush_stdout_stderr();
8954  cmddone:
8955         exitstatus |= ferror(stdout);
8956         clearerr(stdout);
8957         commandname = savecmdname;
8958 //      exsig = 0;
8959         exception_handler = savehandler;
8960
8961         return i;
8962 }
8963
8964 static int
8965 goodname(const char *p)
8966 {
8967         return !*endofname(p);
8968 }
8969
8970
8971 /*
8972  * Search for a command.  This is called before we fork so that the
8973  * location of the command will be available in the parent as well as
8974  * the child.  The check for "goodname" is an overly conservative
8975  * check that the name will not be subject to expansion.
8976  */
8977 static void
8978 prehash(union node *n)
8979 {
8980         struct cmdentry entry;
8981
8982         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8983                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8984 }
8985
8986
8987 /* ============ Builtin commands
8988  *
8989  * Builtin commands whose functions are closely tied to evaluation
8990  * are implemented here.
8991  */
8992
8993 /*
8994  * Handle break and continue commands.  Break, continue, and return are
8995  * all handled by setting the evalskip flag.  The evaluation routines
8996  * above all check this flag, and if it is set they start skipping
8997  * commands rather than executing them.  The variable skipcount is
8998  * the number of loops to break/continue, or the number of function
8999  * levels to return.  (The latter is always 1.)  It should probably
9000  * be an error to break out of more loops than exist, but it isn't
9001  * in the standard shell so we don't make it one here.
9002  */
9003 static int
9004 breakcmd(int argc UNUSED_PARAM, char **argv)
9005 {
9006         int n = argv[1] ? number(argv[1]) : 1;
9007
9008         if (n <= 0)
9009                 ash_msg_and_raise_error(illnum, argv[1]);
9010         if (n > loopnest)
9011                 n = loopnest;
9012         if (n > 0) {
9013                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9014                 skipcount = n;
9015         }
9016         return 0;
9017 }
9018
9019
9020 /* ============ input.c
9021  *
9022  * This implements the input routines used by the parser.
9023  */
9024
9025 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
9026
9027 enum {
9028         INPUT_PUSH_FILE = 1,
9029         INPUT_NOFILE_OK = 2,
9030 };
9031
9032 static int plinno = 1;                  /* input line number */
9033 /* number of characters left in input buffer */
9034 static int parsenleft;                  /* copy of parsefile->nleft */
9035 static int parselleft;                  /* copy of parsefile->lleft */
9036 /* next character in input buffer */
9037 static char *parsenextc;                /* copy of parsefile->nextc */
9038
9039 static smallint checkkwd;
9040 /* values of checkkwd variable */
9041 #define CHKALIAS        0x1
9042 #define CHKKWD          0x2
9043 #define CHKNL           0x4
9044
9045 static void
9046 popstring(void)
9047 {
9048         struct strpush *sp = g_parsefile->strpush;
9049
9050         INT_OFF;
9051 #if ENABLE_ASH_ALIAS
9052         if (sp->ap) {
9053                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
9054                         checkkwd |= CHKALIAS;
9055                 }
9056                 if (sp->string != sp->ap->val) {
9057                         free(sp->string);
9058                 }
9059                 sp->ap->flag &= ~ALIASINUSE;
9060                 if (sp->ap->flag & ALIASDEAD) {
9061                         unalias(sp->ap->name);
9062                 }
9063         }
9064 #endif
9065         parsenextc = sp->prevstring;
9066         parsenleft = sp->prevnleft;
9067 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
9068         g_parsefile->strpush = sp->prev;
9069         if (sp != &(g_parsefile->basestrpush))
9070                 free(sp);
9071         INT_ON;
9072 }
9073
9074 static int
9075 preadfd(void)
9076 {
9077         int nr;
9078         char *buf = g_parsefile->buf;
9079         parsenextc = buf;
9080
9081 #if ENABLE_FEATURE_EDITING
9082  retry:
9083         if (!iflag || g_parsefile->fd)
9084                 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9085         else {
9086 #if ENABLE_FEATURE_TAB_COMPLETION
9087                 line_input_state->path_lookup = pathval();
9088 #endif
9089                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9090                 if (nr == 0) {
9091                         /* Ctrl+C pressed */
9092                         if (trap[SIGINT]) {
9093                                 buf[0] = '\n';
9094                                 buf[1] = '\0';
9095                                 raise(SIGINT);
9096                                 return 1;
9097                         }
9098                         goto retry;
9099                 }
9100                 if (nr < 0 && errno == 0) {
9101                         /* Ctrl+D pressed */
9102                         nr = 0;
9103                 }
9104         }
9105 #else
9106         nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9107 #endif
9108
9109 #if 0
9110 /* nonblock_safe_read() handles this problem */
9111         if (nr < 0) {
9112                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9113                         int flags = fcntl(0, F_GETFL);
9114                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9115                                 flags &= ~O_NONBLOCK;
9116                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9117                                         out2str("sh: turning off NDELAY mode\n");
9118                                         goto retry;
9119                                 }
9120                         }
9121                 }
9122         }
9123 #endif
9124         return nr;
9125 }
9126
9127 /*
9128  * Refill the input buffer and return the next input character:
9129  *
9130  * 1) If a string was pushed back on the input, pop it;
9131  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
9132  *    from a string so we can't refill the buffer, return EOF.
9133  * 3) If the is more stuff in this buffer, use it else call read to fill it.
9134  * 4) Process input up to the next newline, deleting nul characters.
9135  */
9136 static int
9137 preadbuffer(void)
9138 {
9139         char *q;
9140         int more;
9141         char savec;
9142
9143         while (g_parsefile->strpush) {
9144 #if ENABLE_ASH_ALIAS
9145                 if (parsenleft == -1 && g_parsefile->strpush->ap &&
9146                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
9147                         return PEOA;
9148                 }
9149 #endif
9150                 popstring();
9151                 if (--parsenleft >= 0)
9152                         return signed_char2int(*parsenextc++);
9153         }
9154         if (parsenleft == EOF_NLEFT || g_parsefile->buf == NULL)
9155                 return PEOF;
9156         flush_stdout_stderr();
9157
9158         more = parselleft;
9159         if (more <= 0) {
9160  again:
9161                 more = preadfd();
9162                 if (more <= 0) {
9163                         parselleft = parsenleft = EOF_NLEFT;
9164                         return PEOF;
9165                 }
9166         }
9167
9168         q = parsenextc;
9169
9170         /* delete nul characters */
9171         for (;;) {
9172                 int c;
9173
9174                 more--;
9175                 c = *q;
9176
9177                 if (!c)
9178                         memmove(q, q + 1, more);
9179                 else {
9180                         q++;
9181                         if (c == '\n') {
9182                                 parsenleft = q - parsenextc - 1;
9183                                 break;
9184                         }
9185                 }
9186
9187                 if (more <= 0) {
9188                         parsenleft = q - parsenextc - 1;
9189                         if (parsenleft < 0)
9190                                 goto again;
9191                         break;
9192                 }
9193         }
9194         parselleft = more;
9195
9196         savec = *q;
9197         *q = '\0';
9198
9199         if (vflag) {
9200                 out2str(parsenextc);
9201         }
9202
9203         *q = savec;
9204
9205         return signed_char2int(*parsenextc++);
9206 }
9207
9208 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
9209 static int
9210 pgetc(void)
9211 {
9212         return pgetc_as_macro();
9213 }
9214
9215 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9216 #define pgetc_macro() pgetc()
9217 #else
9218 #define pgetc_macro() pgetc_as_macro()
9219 #endif
9220
9221 /*
9222  * Same as pgetc(), but ignores PEOA.
9223  */
9224 #if ENABLE_ASH_ALIAS
9225 static int
9226 pgetc2(void)
9227 {
9228         int c;
9229
9230         do {
9231                 c = pgetc_macro();
9232         } while (c == PEOA);
9233         return c;
9234 }
9235 #else
9236 static int
9237 pgetc2(void)
9238 {
9239         return pgetc_macro();
9240 }
9241 #endif
9242
9243 /*
9244  * Read a line from the script.
9245  */
9246 static char *
9247 pfgets(char *line, int len)
9248 {
9249         char *p = line;
9250         int nleft = len;
9251         int c;
9252
9253         while (--nleft > 0) {
9254                 c = pgetc2();
9255                 if (c == PEOF) {
9256                         if (p == line)
9257                                 return NULL;
9258                         break;
9259                 }
9260                 *p++ = c;
9261                 if (c == '\n')
9262                         break;
9263         }
9264         *p = '\0';
9265         return line;
9266 }
9267
9268 /*
9269  * Undo the last call to pgetc.  Only one character may be pushed back.
9270  * PEOF may be pushed back.
9271  */
9272 static void
9273 pungetc(void)
9274 {
9275         parsenleft++;
9276         parsenextc--;
9277 }
9278
9279 /*
9280  * Push a string back onto the input at this current parsefile level.
9281  * We handle aliases this way.
9282  */
9283 #if !ENABLE_ASH_ALIAS
9284 #define pushstring(s, ap) pushstring(s)
9285 #endif
9286 static void
9287 pushstring(char *s, struct alias *ap)
9288 {
9289         struct strpush *sp;
9290         size_t len;
9291
9292         len = strlen(s);
9293         INT_OFF;
9294 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
9295         if (g_parsefile->strpush) {
9296                 sp = ckzalloc(sizeof(struct strpush));
9297                 sp->prev = g_parsefile->strpush;
9298                 g_parsefile->strpush = sp;
9299         } else
9300                 sp = g_parsefile->strpush = &(g_parsefile->basestrpush);
9301         sp->prevstring = parsenextc;
9302         sp->prevnleft = parsenleft;
9303 #if ENABLE_ASH_ALIAS
9304         sp->ap = ap;
9305         if (ap) {
9306                 ap->flag |= ALIASINUSE;
9307                 sp->string = s;
9308         }
9309 #endif
9310         parsenextc = s;
9311         parsenleft = len;
9312         INT_ON;
9313 }
9314
9315 /*
9316  * To handle the "." command, a stack of input files is used.  Pushfile
9317  * adds a new entry to the stack and popfile restores the previous level.
9318  */
9319 static void
9320 pushfile(void)
9321 {
9322         struct parsefile *pf;
9323
9324         g_parsefile->nleft = parsenleft;
9325         g_parsefile->lleft = parselleft;
9326         g_parsefile->nextc = parsenextc;
9327         g_parsefile->linno = plinno;
9328         pf = ckzalloc(sizeof(*pf));
9329         pf->prev = g_parsefile;
9330         pf->fd = -1;
9331         /*pf->strpush = NULL; - ckzalloc did it */
9332         /*pf->basestrpush.prev = NULL;*/
9333         g_parsefile = pf;
9334 }
9335
9336 static void
9337 popfile(void)
9338 {
9339         struct parsefile *pf = g_parsefile;
9340
9341         INT_OFF;
9342         if (pf->fd >= 0)
9343                 close(pf->fd);
9344         free(pf->buf);
9345         while (pf->strpush)
9346                 popstring();
9347         g_parsefile = pf->prev;
9348         free(pf);
9349         parsenleft = g_parsefile->nleft;
9350         parselleft = g_parsefile->lleft;
9351         parsenextc = g_parsefile->nextc;
9352         plinno = g_parsefile->linno;
9353         INT_ON;
9354 }
9355
9356 /*
9357  * Return to top level.
9358  */
9359 static void
9360 popallfiles(void)
9361 {
9362         while (g_parsefile != &basepf)
9363                 popfile();
9364 }
9365
9366 /*
9367  * Close the file(s) that the shell is reading commands from.  Called
9368  * after a fork is done.
9369  */
9370 static void
9371 closescript(void)
9372 {
9373         popallfiles();
9374         if (g_parsefile->fd > 0) {
9375                 close(g_parsefile->fd);
9376                 g_parsefile->fd = 0;
9377         }
9378 }
9379
9380 /*
9381  * Like setinputfile, but takes an open file descriptor.  Call this with
9382  * interrupts off.
9383  */
9384 static void
9385 setinputfd(int fd, int push)
9386 {
9387         close_on_exec_on(fd);
9388         if (push) {
9389                 pushfile();
9390                 g_parsefile->buf = 0;
9391         }
9392         g_parsefile->fd = fd;
9393         if (g_parsefile->buf == NULL)
9394                 g_parsefile->buf = ckmalloc(IBUFSIZ);
9395         parselleft = parsenleft = 0;
9396         plinno = 1;
9397 }
9398
9399 /*
9400  * Set the input to take input from a file.  If push is set, push the
9401  * old input onto the stack first.
9402  */
9403 static int
9404 setinputfile(const char *fname, int flags)
9405 {
9406         int fd;
9407         int fd2;
9408
9409         INT_OFF;
9410         fd = open(fname, O_RDONLY);
9411         if (fd < 0) {
9412                 if (flags & INPUT_NOFILE_OK)
9413                         goto out;
9414                 ash_msg_and_raise_error("can't open %s", fname);
9415         }
9416         if (fd < 10) {
9417                 fd2 = copyfd(fd, 10);
9418                 close(fd);
9419                 if (fd2 < 0)
9420                         ash_msg_and_raise_error("out of file descriptors");
9421                 fd = fd2;
9422         }
9423         setinputfd(fd, flags & INPUT_PUSH_FILE);
9424  out:
9425         INT_ON;
9426         return fd;
9427 }
9428
9429 /*
9430  * Like setinputfile, but takes input from a string.
9431  */
9432 static void
9433 setinputstring(char *string)
9434 {
9435         INT_OFF;
9436         pushfile();
9437         parsenextc = string;
9438         parsenleft = strlen(string);
9439         g_parsefile->buf = NULL;
9440         plinno = 1;
9441         INT_ON;
9442 }
9443
9444
9445 /* ============ mail.c
9446  *
9447  * Routines to check for mail.
9448  */
9449
9450 #if ENABLE_ASH_MAIL
9451
9452 #define MAXMBOXES 10
9453
9454 /* times of mailboxes */
9455 static time_t mailtime[MAXMBOXES];
9456 /* Set if MAIL or MAILPATH is changed. */
9457 static smallint mail_var_path_changed;
9458
9459 /*
9460  * Print appropriate message(s) if mail has arrived.
9461  * If mail_var_path_changed is set,
9462  * then the value of MAIL has mail_var_path_changed,
9463  * so we just update the values.
9464  */
9465 static void
9466 chkmail(void)
9467 {
9468         const char *mpath;
9469         char *p;
9470         char *q;
9471         time_t *mtp;
9472         struct stackmark smark;
9473         struct stat statb;
9474
9475         setstackmark(&smark);
9476         mpath = mpathset() ? mpathval() : mailval();
9477         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9478                 p = padvance(&mpath, nullstr);
9479                 if (p == NULL)
9480                         break;
9481                 if (*p == '\0')
9482                         continue;
9483                 for (q = p; *q; q++)
9484                         continue;
9485 #if DEBUG
9486                 if (q[-1] != '/')
9487                         abort();
9488 #endif
9489                 q[-1] = '\0';                   /* delete trailing '/' */
9490                 if (stat(p, &statb) < 0) {
9491                         *mtp = 0;
9492                         continue;
9493                 }
9494                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9495                         fprintf(
9496                                 stderr, snlfmt,
9497                                 pathopt ? pathopt : "you have mail"
9498                         );
9499                 }
9500                 *mtp = statb.st_mtime;
9501         }
9502         mail_var_path_changed = 0;
9503         popstackmark(&smark);
9504 }
9505
9506 static void
9507 changemail(const char *val UNUSED_PARAM)
9508 {
9509         mail_var_path_changed = 1;
9510 }
9511
9512 #endif /* ASH_MAIL */
9513
9514
9515 /* ============ ??? */
9516
9517 /*
9518  * Set the shell parameters.
9519  */
9520 static void
9521 setparam(char **argv)
9522 {
9523         char **newparam;
9524         char **ap;
9525         int nparam;
9526
9527         for (nparam = 0; argv[nparam]; nparam++)
9528                 continue;
9529         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9530         while (*argv) {
9531                 *ap++ = ckstrdup(*argv++);
9532         }
9533         *ap = NULL;
9534         freeparam(&shellparam);
9535         shellparam.malloced = 1;
9536         shellparam.nparam = nparam;
9537         shellparam.p = newparam;
9538 #if ENABLE_ASH_GETOPTS
9539         shellparam.optind = 1;
9540         shellparam.optoff = -1;
9541 #endif
9542 }
9543
9544 /*
9545  * Process shell options.  The global variable argptr contains a pointer
9546  * to the argument list; we advance it past the options.
9547  *
9548  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9549  * For a non-interactive shell, an error condition encountered
9550  * by a special built-in ... shall cause the shell to write a diagnostic message
9551  * to standard error and exit as shown in the following table:
9552  * Error                                           Special Built-In
9553  * ...
9554  * Utility syntax error (option or operand error)  Shall exit
9555  * ...
9556  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9557  * we see that bash does not do that (set "finishes" with error code 1 instead,
9558  * and shell continues), and people rely on this behavior!
9559  * Testcase:
9560  * set -o barfoo 2>/dev/null
9561  * echo $?
9562  *
9563  * Oh well. Let's mimic that.
9564  */
9565 static int
9566 plus_minus_o(char *name, int val)
9567 {
9568         int i;
9569
9570         if (name) {
9571                 for (i = 0; i < NOPTS; i++) {
9572                         if (strcmp(name, optnames(i)) == 0) {
9573                                 optlist[i] = val;
9574                                 return 0;
9575                         }
9576                 }
9577                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9578                 return 1;
9579         }
9580         for (i = 0; i < NOPTS; i++) {
9581                 if (val) {
9582                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9583                 } else {
9584                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9585                 }
9586         }
9587         return 0;
9588 }
9589 static void
9590 setoption(int flag, int val)
9591 {
9592         int i;
9593
9594         for (i = 0; i < NOPTS; i++) {
9595                 if (optletters(i) == flag) {
9596                         optlist[i] = val;
9597                         return;
9598                 }
9599         }
9600         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9601         /* NOTREACHED */
9602 }
9603 static int
9604 options(int cmdline)
9605 {
9606         char *p;
9607         int val;
9608         int c;
9609
9610         if (cmdline)
9611                 minusc = NULL;
9612         while ((p = *argptr) != NULL) {
9613                 c = *p++;
9614                 if (c != '-' && c != '+')
9615                         break;
9616                 argptr++;
9617                 val = 0; /* val = 0 if c == '+' */
9618                 if (c == '-') {
9619                         val = 1;
9620                         if (p[0] == '\0' || LONE_DASH(p)) {
9621                                 if (!cmdline) {
9622                                         /* "-" means turn off -x and -v */
9623                                         if (p[0] == '\0')
9624                                                 xflag = vflag = 0;
9625                                         /* "--" means reset params */
9626                                         else if (*argptr == NULL)
9627                                                 setparam(argptr);
9628                                 }
9629                                 break;    /* "-" or  "--" terminates options */
9630                         }
9631                 }
9632                 /* first char was + or - */
9633                 while ((c = *p++) != '\0') {
9634                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9635                         if (c == 'c' && cmdline) {
9636                                 minusc = p;     /* command is after shell args */
9637                         } else if (c == 'o') {
9638                                 if (plus_minus_o(*argptr, val)) {
9639                                         /* it already printed err message */
9640                                         return 1; /* error */
9641                                 }
9642                                 if (*argptr)
9643                                         argptr++;
9644                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9645                                 isloginsh = 1;
9646                         /* bash does not accept +-login, we also won't */
9647                         } else if (cmdline && val && (c == '-')) { /* long options */
9648                                 if (strcmp(p, "login") == 0)
9649                                         isloginsh = 1;
9650                                 break;
9651                         } else {
9652                                 setoption(c, val);
9653                         }
9654                 }
9655         }
9656         return 0;
9657 }
9658
9659 /*
9660  * The shift builtin command.
9661  */
9662 static int
9663 shiftcmd(int argc UNUSED_PARAM, char **argv)
9664 {
9665         int n;
9666         char **ap1, **ap2;
9667
9668         n = 1;
9669         if (argv[1])
9670                 n = number(argv[1]);
9671         if (n > shellparam.nparam)
9672                 n = 0; /* bash compat, was = shellparam.nparam; */
9673         INT_OFF;
9674         shellparam.nparam -= n;
9675         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9676                 if (shellparam.malloced)
9677                         free(*ap1);
9678         }
9679         ap2 = shellparam.p;
9680         while ((*ap2++ = *ap1++) != NULL)
9681                 continue;
9682 #if ENABLE_ASH_GETOPTS
9683         shellparam.optind = 1;
9684         shellparam.optoff = -1;
9685 #endif
9686         INT_ON;
9687         return 0;
9688 }
9689
9690 /*
9691  * POSIX requires that 'set' (but not export or readonly) output the
9692  * variables in lexicographic order - by the locale's collating order (sigh).
9693  * Maybe we could keep them in an ordered balanced binary tree
9694  * instead of hashed lists.
9695  * For now just roll 'em through qsort for printing...
9696  */
9697 static int
9698 showvars(const char *sep_prefix, int on, int off)
9699 {
9700         const char *sep;
9701         char **ep, **epend;
9702
9703         ep = listvars(on, off, &epend);
9704         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9705
9706         sep = *sep_prefix ? " " : sep_prefix;
9707
9708         for (; ep < epend; ep++) {
9709                 const char *p;
9710                 const char *q;
9711
9712                 p = strchrnul(*ep, '=');
9713                 q = nullstr;
9714                 if (*p)
9715                         q = single_quote(++p);
9716                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9717         }
9718         return 0;
9719 }
9720
9721 /*
9722  * The set command builtin.
9723  */
9724 static int
9725 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9726 {
9727         int retval;
9728
9729         if (!argv[1])
9730                 return showvars(nullstr, 0, VUNSET);
9731         INT_OFF;
9732         retval = 1;
9733         if (!options(0)) { /* if no parse error... */
9734                 retval = 0;
9735                 optschanged();
9736                 if (*argptr != NULL) {
9737                         setparam(argptr);
9738                 }
9739         }
9740         INT_ON;
9741         return retval;
9742 }
9743
9744 #if ENABLE_ASH_RANDOM_SUPPORT
9745 static void
9746 change_random(const char *value)
9747 {
9748         /* Galois LFSR parameter */
9749         /* Taps at 32 31 29 1: */
9750         enum { MASK = 0x8000000b };
9751         /* Another example - taps at 32 31 30 10: */
9752         /* MASK = 0x00400007 */
9753
9754         if (value == NULL) {
9755                 /* "get", generate */
9756                 uint32_t t;
9757
9758                 /* LCG has period of 2^32 and alternating lowest bit */
9759                 random_LCG = 1664525 * random_LCG + 1013904223;
9760                 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9761                 t = (random_galois_LFSR << 1);
9762                 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9763                         t ^= MASK;
9764                 random_galois_LFSR = t;
9765                 /* Both are weak, combining them gives better randomness
9766                  * and ~2^64 period. & 0x7fff is probably bash compat
9767                  * for $RANDOM range. Combining with subtraction is
9768                  * just for fun. + and ^ would work equally well. */
9769                 t = (t - random_LCG) & 0x7fff;
9770                 /* set without recursion */
9771                 setvar(vrandom.text, utoa(t), VNOFUNC);
9772                 vrandom.flags &= ~VNOFUNC;
9773         } else {
9774                 /* set/reset */
9775                 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9776         }
9777 }
9778 #endif
9779
9780 #if ENABLE_ASH_GETOPTS
9781 static int
9782 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9783 {
9784         char *p, *q;
9785         char c = '?';
9786         int done = 0;
9787         int err = 0;
9788         char s[12];
9789         char **optnext;
9790
9791         if (*param_optind < 1)
9792                 return 1;
9793         optnext = optfirst + *param_optind - 1;
9794
9795         if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9796                 p = NULL;
9797         else
9798                 p = optnext[-1] + *optoff;
9799         if (p == NULL || *p == '\0') {
9800                 /* Current word is done, advance */
9801                 p = *optnext;
9802                 if (p == NULL || *p != '-' || *++p == '\0') {
9803  atend:
9804                         p = NULL;
9805                         done = 1;
9806                         goto out;
9807                 }
9808                 optnext++;
9809                 if (LONE_DASH(p))        /* check for "--" */
9810                         goto atend;
9811         }
9812
9813         c = *p++;
9814         for (q = optstr; *q != c;) {
9815                 if (*q == '\0') {
9816                         if (optstr[0] == ':') {
9817                                 s[0] = c;
9818                                 s[1] = '\0';
9819                                 err |= setvarsafe("OPTARG", s, 0);
9820                         } else {
9821                                 fprintf(stderr, "Illegal option -%c\n", c);
9822                                 unsetvar("OPTARG");
9823                         }
9824                         c = '?';
9825                         goto out;
9826                 }
9827                 if (*++q == ':')
9828                         q++;
9829         }
9830
9831         if (*++q == ':') {
9832                 if (*p == '\0' && (p = *optnext) == NULL) {
9833                         if (optstr[0] == ':') {
9834                                 s[0] = c;
9835                                 s[1] = '\0';
9836                                 err |= setvarsafe("OPTARG", s, 0);
9837                                 c = ':';
9838                         } else {
9839                                 fprintf(stderr, "No arg for -%c option\n", c);
9840                                 unsetvar("OPTARG");
9841                                 c = '?';
9842                         }
9843                         goto out;
9844                 }
9845
9846                 if (p == *optnext)
9847                         optnext++;
9848                 err |= setvarsafe("OPTARG", p, 0);
9849                 p = NULL;
9850         } else
9851                 err |= setvarsafe("OPTARG", nullstr, 0);
9852  out:
9853         *optoff = p ? p - *(optnext - 1) : -1;
9854         *param_optind = optnext - optfirst + 1;
9855         fmtstr(s, sizeof(s), "%d", *param_optind);
9856         err |= setvarsafe("OPTIND", s, VNOFUNC);
9857         s[0] = c;
9858         s[1] = '\0';
9859         err |= setvarsafe(optvar, s, 0);
9860         if (err) {
9861                 *param_optind = 1;
9862                 *optoff = -1;
9863                 flush_stdout_stderr();
9864                 raise_exception(EXERROR);
9865         }
9866         return done;
9867 }
9868
9869 /*
9870  * The getopts builtin.  Shellparam.optnext points to the next argument
9871  * to be processed.  Shellparam.optptr points to the next character to
9872  * be processed in the current argument.  If shellparam.optnext is NULL,
9873  * then it's the first time getopts has been called.
9874  */
9875 static int
9876 getoptscmd(int argc, char **argv)
9877 {
9878         char **optbase;
9879
9880         if (argc < 3)
9881                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9882         if (argc == 3) {
9883                 optbase = shellparam.p;
9884                 if (shellparam.optind > shellparam.nparam + 1) {
9885                         shellparam.optind = 1;
9886                         shellparam.optoff = -1;
9887                 }
9888         } else {
9889                 optbase = &argv[3];
9890                 if (shellparam.optind > argc - 2) {
9891                         shellparam.optind = 1;
9892                         shellparam.optoff = -1;
9893                 }
9894         }
9895
9896         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9897                         &shellparam.optoff);
9898 }
9899 #endif /* ASH_GETOPTS */
9900
9901
9902 /* ============ Shell parser */
9903
9904 struct heredoc {
9905         struct heredoc *next;   /* next here document in list */
9906         union node *here;       /* redirection node */
9907         char *eofmark;          /* string indicating end of input */
9908         smallint striptabs;     /* if set, strip leading tabs */
9909 };
9910
9911 static smallint tokpushback;           /* last token pushed back */
9912 static smallint parsebackquote;        /* nonzero if we are inside backquotes */
9913 static smallint quoteflag;             /* set if (part of) last token was quoted */
9914 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
9915 static struct heredoc *heredoclist;    /* list of here documents to read */
9916 static char *wordtext;                 /* text of last word returned by readtoken */
9917 static struct nodelist *backquotelist;
9918 static union node *redirnode;
9919 static struct heredoc *heredoc;
9920 /*
9921  * NEOF is returned by parsecmd when it encounters an end of file.  It
9922  * must be distinct from NULL, so we use the address of a variable that
9923  * happens to be handy.
9924  */
9925 #define NEOF ((union node *)&tokpushback)
9926
9927 static void raise_error_syntax(const char *) NORETURN;
9928 static void
9929 raise_error_syntax(const char *msg)
9930 {
9931         ash_msg_and_raise_error("syntax error: %s", msg);
9932         /* NOTREACHED */
9933 }
9934
9935 /*
9936  * Called when an unexpected token is read during the parse.  The argument
9937  * is the token that is expected, or -1 if more than one type of token can
9938  * occur at this point.
9939  */
9940 static void raise_error_unexpected_syntax(int) NORETURN;
9941 static void
9942 raise_error_unexpected_syntax(int token)
9943 {
9944         char msg[64];
9945         int l;
9946
9947         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9948         if (token >= 0)
9949                 sprintf(msg + l, " (expecting %s)", tokname(token));
9950         raise_error_syntax(msg);
9951         /* NOTREACHED */
9952 }
9953
9954 #define EOFMARKLEN 79
9955
9956 /* parsing is heavily cross-recursive, need these forward decls */
9957 static union node *andor(void);
9958 static union node *pipeline(void);
9959 static union node *parse_command(void);
9960 static void parseheredoc(void);
9961 static char peektoken(void);
9962 static int readtoken(void);
9963
9964 static union node *
9965 list(int nlflag)
9966 {
9967         union node *n1, *n2, *n3;
9968         int tok;
9969
9970         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9971         if (nlflag == 2 && peektoken())
9972                 return NULL;
9973         n1 = NULL;
9974         for (;;) {
9975                 n2 = andor();
9976                 tok = readtoken();
9977                 if (tok == TBACKGND) {
9978                         if (n2->type == NPIPE) {
9979                                 n2->npipe.pipe_backgnd = 1;
9980                         } else {
9981                                 if (n2->type != NREDIR) {
9982                                         n3 = stzalloc(sizeof(struct nredir));
9983                                         n3->nredir.n = n2;
9984                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
9985                                         n2 = n3;
9986                                 }
9987                                 n2->type = NBACKGND;
9988                         }
9989                 }
9990                 if (n1 == NULL) {
9991                         n1 = n2;
9992                 } else {
9993                         n3 = stzalloc(sizeof(struct nbinary));
9994                         n3->type = NSEMI;
9995                         n3->nbinary.ch1 = n1;
9996                         n3->nbinary.ch2 = n2;
9997                         n1 = n3;
9998                 }
9999                 switch (tok) {
10000                 case TBACKGND:
10001                 case TSEMI:
10002                         tok = readtoken();
10003                         /* fall through */
10004                 case TNL:
10005                         if (tok == TNL) {
10006                                 parseheredoc();
10007                                 if (nlflag == 1)
10008                                         return n1;
10009                         } else {
10010                                 tokpushback = 1;
10011                         }
10012                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10013                         if (peektoken())
10014                                 return n1;
10015                         break;
10016                 case TEOF:
10017                         if (heredoclist)
10018                                 parseheredoc();
10019                         else
10020                                 pungetc();              /* push back EOF on input */
10021                         return n1;
10022                 default:
10023                         if (nlflag == 1)
10024                                 raise_error_unexpected_syntax(-1);
10025                         tokpushback = 1;
10026                         return n1;
10027                 }
10028         }
10029 }
10030
10031 static union node *
10032 andor(void)
10033 {
10034         union node *n1, *n2, *n3;
10035         int t;
10036
10037         n1 = pipeline();
10038         for (;;) {
10039                 t = readtoken();
10040                 if (t == TAND) {
10041                         t = NAND;
10042                 } else if (t == TOR) {
10043                         t = NOR;
10044                 } else {
10045                         tokpushback = 1;
10046                         return n1;
10047                 }
10048                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10049                 n2 = pipeline();
10050                 n3 = stzalloc(sizeof(struct nbinary));
10051                 n3->type = t;
10052                 n3->nbinary.ch1 = n1;
10053                 n3->nbinary.ch2 = n2;
10054                 n1 = n3;
10055         }
10056 }
10057
10058 static union node *
10059 pipeline(void)
10060 {
10061         union node *n1, *n2, *pipenode;
10062         struct nodelist *lp, *prev;
10063         int negate;
10064
10065         negate = 0;
10066         TRACE(("pipeline: entered\n"));
10067         if (readtoken() == TNOT) {
10068                 negate = !negate;
10069                 checkkwd = CHKKWD | CHKALIAS;
10070         } else
10071                 tokpushback = 1;
10072         n1 = parse_command();
10073         if (readtoken() == TPIPE) {
10074                 pipenode = stzalloc(sizeof(struct npipe));
10075                 pipenode->type = NPIPE;
10076                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10077                 lp = stzalloc(sizeof(struct nodelist));
10078                 pipenode->npipe.cmdlist = lp;
10079                 lp->n = n1;
10080                 do {
10081                         prev = lp;
10082                         lp = stzalloc(sizeof(struct nodelist));
10083                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10084                         lp->n = parse_command();
10085                         prev->next = lp;
10086                 } while (readtoken() == TPIPE);
10087                 lp->next = NULL;
10088                 n1 = pipenode;
10089         }
10090         tokpushback = 1;
10091         if (negate) {
10092                 n2 = stzalloc(sizeof(struct nnot));
10093                 n2->type = NNOT;
10094                 n2->nnot.com = n1;
10095                 return n2;
10096         }
10097         return n1;
10098 }
10099
10100 static union node *
10101 makename(void)
10102 {
10103         union node *n;
10104
10105         n = stzalloc(sizeof(struct narg));
10106         n->type = NARG;
10107         /*n->narg.next = NULL; - stzalloc did it */
10108         n->narg.text = wordtext;
10109         n->narg.backquote = backquotelist;
10110         return n;
10111 }
10112
10113 static void
10114 fixredir(union node *n, const char *text, int err)
10115 {
10116         int fd;
10117
10118         TRACE(("Fix redir %s %d\n", text, err));
10119         if (!err)
10120                 n->ndup.vname = NULL;
10121
10122         fd = bb_strtou(text, NULL, 10);
10123         if (!errno && fd >= 0)
10124                 n->ndup.dupfd = fd;
10125         else if (LONE_DASH(text))
10126                 n->ndup.dupfd = -1;
10127         else {
10128                 if (err)
10129                         raise_error_syntax("Bad fd number");
10130                 n->ndup.vname = makename();
10131         }
10132 }
10133
10134 /*
10135  * Returns true if the text contains nothing to expand (no dollar signs
10136  * or backquotes).
10137  */
10138 static int
10139 noexpand(char *text)
10140 {
10141         char *p;
10142         char c;
10143
10144         p = text;
10145         while ((c = *p++) != '\0') {
10146                 if (c == CTLQUOTEMARK)
10147                         continue;
10148                 if (c == CTLESC)
10149                         p++;
10150                 else if (SIT(c, BASESYNTAX) == CCTL)
10151                         return 0;
10152         }
10153         return 1;
10154 }
10155
10156 static void
10157 parsefname(void)
10158 {
10159         union node *n = redirnode;
10160
10161         if (readtoken() != TWORD)
10162                 raise_error_unexpected_syntax(-1);
10163         if (n->type == NHERE) {
10164                 struct heredoc *here = heredoc;
10165                 struct heredoc *p;
10166                 int i;
10167
10168                 if (quoteflag == 0)
10169                         n->type = NXHERE;
10170                 TRACE(("Here document %d\n", n->type));
10171                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10172                         raise_error_syntax("Illegal eof marker for << redirection");
10173                 rmescapes(wordtext);
10174                 here->eofmark = wordtext;
10175                 here->next = NULL;
10176                 if (heredoclist == NULL)
10177                         heredoclist = here;
10178                 else {
10179                         for (p = heredoclist; p->next; p = p->next)
10180                                 continue;
10181                         p->next = here;
10182                 }
10183         } else if (n->type == NTOFD || n->type == NFROMFD) {
10184                 fixredir(n, wordtext, 0);
10185         } else {
10186                 n->nfile.fname = makename();
10187         }
10188 }
10189
10190 static union node *
10191 simplecmd(void)
10192 {
10193         union node *args, **app;
10194         union node *n = NULL;
10195         union node *vars, **vpp;
10196         union node **rpp, *redir;
10197         int savecheckkwd;
10198 #if ENABLE_ASH_BASH_COMPAT
10199         smallint double_brackets_flag = 0;
10200 #endif
10201
10202         args = NULL;
10203         app = &args;
10204         vars = NULL;
10205         vpp = &vars;
10206         redir = NULL;
10207         rpp = &redir;
10208
10209         savecheckkwd = CHKALIAS;
10210         for (;;) {
10211                 int t;
10212                 checkkwd = savecheckkwd;
10213                 t = readtoken();
10214                 switch (t) {
10215 #if ENABLE_ASH_BASH_COMPAT
10216                 case TAND: /* "&&" */
10217                 case TOR: /* "||" */
10218                         if (!double_brackets_flag) {
10219                                 tokpushback = 1;
10220                                 goto out;
10221                         }
10222                         wordtext = (char *) (t == TAND ? "-a" : "-o");
10223 #endif
10224                 case TWORD:
10225                         n = stzalloc(sizeof(struct narg));
10226                         n->type = NARG;
10227                         /*n->narg.next = NULL; - stzalloc did it */
10228                         n->narg.text = wordtext;
10229 #if ENABLE_ASH_BASH_COMPAT
10230                         if (strcmp("[[", wordtext) == 0)
10231                                 double_brackets_flag = 1;
10232                         else if (strcmp("]]", wordtext) == 0)
10233                                 double_brackets_flag = 0;
10234 #endif
10235                         n->narg.backquote = backquotelist;
10236                         if (savecheckkwd && isassignment(wordtext)) {
10237                                 *vpp = n;
10238                                 vpp = &n->narg.next;
10239                         } else {
10240                                 *app = n;
10241                                 app = &n->narg.next;
10242                                 savecheckkwd = 0;
10243                         }
10244                         break;
10245                 case TREDIR:
10246                         *rpp = n = redirnode;
10247                         rpp = &n->nfile.next;
10248                         parsefname();   /* read name of redirection file */
10249                         break;
10250                 case TLP:
10251                         if (args && app == &args->narg.next
10252                          && !vars && !redir
10253                         ) {
10254                                 struct builtincmd *bcmd;
10255                                 const char *name;
10256
10257                                 /* We have a function */
10258                                 if (readtoken() != TRP)
10259                                         raise_error_unexpected_syntax(TRP);
10260                                 name = n->narg.text;
10261                                 if (!goodname(name)
10262                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10263                                 ) {
10264                                         raise_error_syntax("Bad function name");
10265                                 }
10266                                 n->type = NDEFUN;
10267                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10268                                 n->narg.next = parse_command();
10269                                 return n;
10270                         }
10271                         /* fall through */
10272                 default:
10273                         tokpushback = 1;
10274                         goto out;
10275                 }
10276         }
10277  out:
10278         *app = NULL;
10279         *vpp = NULL;
10280         *rpp = NULL;
10281         n = stzalloc(sizeof(struct ncmd));
10282         n->type = NCMD;
10283         n->ncmd.args = args;
10284         n->ncmd.assign = vars;
10285         n->ncmd.redirect = redir;
10286         return n;
10287 }
10288
10289 static union node *
10290 parse_command(void)
10291 {
10292         union node *n1, *n2;
10293         union node *ap, **app;
10294         union node *cp, **cpp;
10295         union node *redir, **rpp;
10296         union node **rpp2;
10297         int t;
10298
10299         redir = NULL;
10300         rpp2 = &redir;
10301
10302         switch (readtoken()) {
10303         default:
10304                 raise_error_unexpected_syntax(-1);
10305                 /* NOTREACHED */
10306         case TIF:
10307                 n1 = stzalloc(sizeof(struct nif));
10308                 n1->type = NIF;
10309                 n1->nif.test = list(0);
10310                 if (readtoken() != TTHEN)
10311                         raise_error_unexpected_syntax(TTHEN);
10312                 n1->nif.ifpart = list(0);
10313                 n2 = n1;
10314                 while (readtoken() == TELIF) {
10315                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
10316                         n2 = n2->nif.elsepart;
10317                         n2->type = NIF;
10318                         n2->nif.test = list(0);
10319                         if (readtoken() != TTHEN)
10320                                 raise_error_unexpected_syntax(TTHEN);
10321                         n2->nif.ifpart = list(0);
10322                 }
10323                 if (lasttoken == TELSE)
10324                         n2->nif.elsepart = list(0);
10325                 else {
10326                         n2->nif.elsepart = NULL;
10327                         tokpushback = 1;
10328                 }
10329                 t = TFI;
10330                 break;
10331         case TWHILE:
10332         case TUNTIL: {
10333                 int got;
10334                 n1 = stzalloc(sizeof(struct nbinary));
10335                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10336                 n1->nbinary.ch1 = list(0);
10337                 got = readtoken();
10338                 if (got != TDO) {
10339                         TRACE(("expecting DO got %s %s\n", tokname(got),
10340                                         got == TWORD ? wordtext : ""));
10341                         raise_error_unexpected_syntax(TDO);
10342                 }
10343                 n1->nbinary.ch2 = list(0);
10344                 t = TDONE;
10345                 break;
10346         }
10347         case TFOR:
10348                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10349                         raise_error_syntax("Bad for loop variable");
10350                 n1 = stzalloc(sizeof(struct nfor));
10351                 n1->type = NFOR;
10352                 n1->nfor.var = wordtext;
10353                 checkkwd = CHKKWD | CHKALIAS;
10354                 if (readtoken() == TIN) {
10355                         app = &ap;
10356                         while (readtoken() == TWORD) {
10357                                 n2 = stzalloc(sizeof(struct narg));
10358                                 n2->type = NARG;
10359                                 /*n2->narg.next = NULL; - stzalloc did it */
10360                                 n2->narg.text = wordtext;
10361                                 n2->narg.backquote = backquotelist;
10362                                 *app = n2;
10363                                 app = &n2->narg.next;
10364                         }
10365                         *app = NULL;
10366                         n1->nfor.args = ap;
10367                         if (lasttoken != TNL && lasttoken != TSEMI)
10368                                 raise_error_unexpected_syntax(-1);
10369                 } else {
10370                         n2 = stzalloc(sizeof(struct narg));
10371                         n2->type = NARG;
10372                         /*n2->narg.next = NULL; - stzalloc did it */
10373                         n2->narg.text = (char *)dolatstr;
10374                         /*n2->narg.backquote = NULL;*/
10375                         n1->nfor.args = n2;
10376                         /*
10377                          * Newline or semicolon here is optional (but note
10378                          * that the original Bourne shell only allowed NL).
10379                          */
10380                         if (lasttoken != TNL && lasttoken != TSEMI)
10381                                 tokpushback = 1;
10382                 }
10383                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10384                 if (readtoken() != TDO)
10385                         raise_error_unexpected_syntax(TDO);
10386                 n1->nfor.body = list(0);
10387                 t = TDONE;
10388                 break;
10389         case TCASE:
10390                 n1 = stzalloc(sizeof(struct ncase));
10391                 n1->type = NCASE;
10392                 if (readtoken() != TWORD)
10393                         raise_error_unexpected_syntax(TWORD);
10394                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10395                 n2->type = NARG;
10396                 /*n2->narg.next = NULL; - stzalloc did it */
10397                 n2->narg.text = wordtext;
10398                 n2->narg.backquote = backquotelist;
10399                 do {
10400                         checkkwd = CHKKWD | CHKALIAS;
10401                 } while (readtoken() == TNL);
10402                 if (lasttoken != TIN)
10403                         raise_error_unexpected_syntax(TIN);
10404                 cpp = &n1->ncase.cases;
10405  next_case:
10406                 checkkwd = CHKNL | CHKKWD;
10407                 t = readtoken();
10408                 while (t != TESAC) {
10409                         if (lasttoken == TLP)
10410                                 readtoken();
10411                         *cpp = cp = stzalloc(sizeof(struct nclist));
10412                         cp->type = NCLIST;
10413                         app = &cp->nclist.pattern;
10414                         for (;;) {
10415                                 *app = ap = stzalloc(sizeof(struct narg));
10416                                 ap->type = NARG;
10417                                 /*ap->narg.next = NULL; - stzalloc did it */
10418                                 ap->narg.text = wordtext;
10419                                 ap->narg.backquote = backquotelist;
10420                                 if (readtoken() != TPIPE)
10421                                         break;
10422                                 app = &ap->narg.next;
10423                                 readtoken();
10424                         }
10425                         //ap->narg.next = NULL;
10426                         if (lasttoken != TRP)
10427                                 raise_error_unexpected_syntax(TRP);
10428                         cp->nclist.body = list(2);
10429
10430                         cpp = &cp->nclist.next;
10431
10432                         checkkwd = CHKNL | CHKKWD;
10433                         t = readtoken();
10434                         if (t != TESAC) {
10435                                 if (t != TENDCASE)
10436                                         raise_error_unexpected_syntax(TENDCASE);
10437                                 goto next_case;
10438                         }
10439                 }
10440                 *cpp = NULL;
10441                 goto redir;
10442         case TLP:
10443                 n1 = stzalloc(sizeof(struct nredir));
10444                 n1->type = NSUBSHELL;
10445                 n1->nredir.n = list(0);
10446                 /*n1->nredir.redirect = NULL; - stzalloc did it */
10447                 t = TRP;
10448                 break;
10449         case TBEGIN:
10450                 n1 = list(0);
10451                 t = TEND;
10452                 break;
10453         case TWORD:
10454         case TREDIR:
10455                 tokpushback = 1;
10456                 return simplecmd();
10457         }
10458
10459         if (readtoken() != t)
10460                 raise_error_unexpected_syntax(t);
10461
10462  redir:
10463         /* Now check for redirection which may follow command */
10464         checkkwd = CHKKWD | CHKALIAS;
10465         rpp = rpp2;
10466         while (readtoken() == TREDIR) {
10467                 *rpp = n2 = redirnode;
10468                 rpp = &n2->nfile.next;
10469                 parsefname();
10470         }
10471         tokpushback = 1;
10472         *rpp = NULL;
10473         if (redir) {
10474                 if (n1->type != NSUBSHELL) {
10475                         n2 = stzalloc(sizeof(struct nredir));
10476                         n2->type = NREDIR;
10477                         n2->nredir.n = n1;
10478                         n1 = n2;
10479                 }
10480                 n1->nredir.redirect = redir;
10481         }
10482         return n1;
10483 }
10484
10485 #if ENABLE_ASH_BASH_COMPAT
10486 static int decode_dollar_squote(void)
10487 {
10488         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10489         int c, cnt;
10490         char *p;
10491         char buf[4];
10492
10493         c = pgetc();
10494         p = strchr(C_escapes, c);
10495         if (p) {
10496                 buf[0] = c;
10497                 p = buf;
10498                 cnt = 3;
10499                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10500                         do {
10501                                 c = pgetc();
10502                                 *++p = c;
10503                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
10504                         pungetc();
10505                 } else if (c == 'x') { /* \xHH */
10506                         do {
10507                                 c = pgetc();
10508                                 *++p = c;
10509                         } while (isxdigit(c) && --cnt);
10510                         pungetc();
10511                         if (cnt == 3) { /* \x but next char is "bad" */
10512                                 c = 'x';
10513                                 goto unrecognized;
10514                         }
10515                 } else { /* simple seq like \\ or \t */
10516                         p++;
10517                 }
10518                 *p = '\0';
10519                 p = buf;
10520                 c = bb_process_escape_sequence((void*)&p);
10521         } else { /* unrecognized "\z": print both chars unless ' or " */
10522                 if (c != '\'' && c != '"') {
10523  unrecognized:
10524                         c |= 0x100; /* "please encode \, then me" */
10525                 }
10526         }
10527         return c;
10528 }
10529 #endif
10530
10531 /*
10532  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10533  * is not NULL, read a here document.  In the latter case, eofmark is the
10534  * word which marks the end of the document and striptabs is true if
10535  * leading tabs should be stripped from the document.  The argument firstc
10536  * is the first character of the input token or document.
10537  *
10538  * Because C does not have internal subroutines, I have simulated them
10539  * using goto's to implement the subroutine linkage.  The following macros
10540  * will run code that appears at the end of readtoken1.
10541  */
10542 #define CHECKEND()      {goto checkend; checkend_return:;}
10543 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10544 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10545 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10546 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10547 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10548 static int
10549 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10550 {
10551         /* NB: syntax parameter fits into smallint */
10552         int c = firstc;
10553         char *out;
10554         int len;
10555         char line[EOFMARKLEN + 1];
10556         struct nodelist *bqlist;
10557         smallint quotef;
10558         smallint dblquote;
10559         smallint oldstyle;
10560         smallint prevsyntax; /* syntax before arithmetic */
10561 #if ENABLE_ASH_EXPAND_PRMT
10562         smallint pssyntax;   /* we are expanding a prompt string */
10563 #endif
10564         int varnest;         /* levels of variables expansion */
10565         int arinest;         /* levels of arithmetic expansion */
10566         int parenlevel;      /* levels of parens in arithmetic */
10567         int dqvarnest;       /* levels of variables expansion within double quotes */
10568
10569         USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10570
10571 #if __GNUC__
10572         /* Avoid longjmp clobbering */
10573         (void) &out;
10574         (void) &quotef;
10575         (void) &dblquote;
10576         (void) &varnest;
10577         (void) &arinest;
10578         (void) &parenlevel;
10579         (void) &dqvarnest;
10580         (void) &oldstyle;
10581         (void) &prevsyntax;
10582         (void) &syntax;
10583 #endif
10584         startlinno = plinno;
10585         bqlist = NULL;
10586         quotef = 0;
10587         oldstyle = 0;
10588         prevsyntax = 0;
10589 #if ENABLE_ASH_EXPAND_PRMT
10590         pssyntax = (syntax == PSSYNTAX);
10591         if (pssyntax)
10592                 syntax = DQSYNTAX;
10593 #endif
10594         dblquote = (syntax == DQSYNTAX);
10595         varnest = 0;
10596         arinest = 0;
10597         parenlevel = 0;
10598         dqvarnest = 0;
10599
10600         STARTSTACKSTR(out);
10601         loop: { /* for each line, until end of word */
10602                 CHECKEND();     /* set c to PEOF if at end of here document */
10603                 for (;;) {      /* until end of line or end of word */
10604                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10605                         switch (SIT(c, syntax)) {
10606                         case CNL:       /* '\n' */
10607                                 if (syntax == BASESYNTAX)
10608                                         goto endword;   /* exit outer loop */
10609                                 USTPUTC(c, out);
10610                                 plinno++;
10611                                 if (doprompt)
10612                                         setprompt(2);
10613                                 c = pgetc();
10614                                 goto loop;              /* continue outer loop */
10615                         case CWORD:
10616                                 USTPUTC(c, out);
10617                                 break;
10618                         case CCTL:
10619                                 if (eofmark == NULL || dblquote)
10620                                         USTPUTC(CTLESC, out);
10621 #if ENABLE_ASH_BASH_COMPAT
10622                                 if (c == '\\' && bash_dollar_squote) {
10623                                         c = decode_dollar_squote();
10624                                         if (c & 0x100) {
10625                                                 USTPUTC('\\', out);
10626                                                 c = (unsigned char)c;
10627                                         }
10628                                 }
10629 #endif
10630                                 USTPUTC(c, out);
10631                                 break;
10632                         case CBACK:     /* backslash */
10633                                 c = pgetc2();
10634                                 if (c == PEOF) {
10635                                         USTPUTC(CTLESC, out);
10636                                         USTPUTC('\\', out);
10637                                         pungetc();
10638                                 } else if (c == '\n') {
10639                                         if (doprompt)
10640                                                 setprompt(2);
10641                                 } else {
10642 #if ENABLE_ASH_EXPAND_PRMT
10643                                         if (c == '$' && pssyntax) {
10644                                                 USTPUTC(CTLESC, out);
10645                                                 USTPUTC('\\', out);
10646                                         }
10647 #endif
10648                                         if (dblquote && c != '\\'
10649                                          && c != '`' && c != '$'
10650                                          && (c != '"' || eofmark != NULL)
10651                                         ) {
10652                                                 USTPUTC(CTLESC, out);
10653                                                 USTPUTC('\\', out);
10654                                         }
10655                                         if (SIT(c, SQSYNTAX) == CCTL)
10656                                                 USTPUTC(CTLESC, out);
10657                                         USTPUTC(c, out);
10658                                         quotef = 1;
10659                                 }
10660                                 break;
10661                         case CSQUOTE:
10662                                 syntax = SQSYNTAX;
10663  quotemark:
10664                                 if (eofmark == NULL) {
10665                                         USTPUTC(CTLQUOTEMARK, out);
10666                                 }
10667                                 break;
10668                         case CDQUOTE:
10669                                 syntax = DQSYNTAX;
10670                                 dblquote = 1;
10671                                 goto quotemark;
10672                         case CENDQUOTE:
10673                                 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10674                                 if (eofmark != NULL && arinest == 0
10675                                  && varnest == 0
10676                                 ) {
10677                                         USTPUTC(c, out);
10678                                 } else {
10679                                         if (dqvarnest == 0) {
10680                                                 syntax = BASESYNTAX;
10681                                                 dblquote = 0;
10682                                         }
10683                                         quotef = 1;
10684                                         goto quotemark;
10685                                 }
10686                                 break;
10687                         case CVAR:      /* '$' */
10688                                 PARSESUB();             /* parse substitution */
10689                                 break;
10690                         case CENDVAR:   /* '}' */
10691                                 if (varnest > 0) {
10692                                         varnest--;
10693                                         if (dqvarnest > 0) {
10694                                                 dqvarnest--;
10695                                         }
10696                                         USTPUTC(CTLENDVAR, out);
10697                                 } else {
10698                                         USTPUTC(c, out);
10699                                 }
10700                                 break;
10701 #if ENABLE_ASH_MATH_SUPPORT
10702                         case CLP:       /* '(' in arithmetic */
10703                                 parenlevel++;
10704                                 USTPUTC(c, out);
10705                                 break;
10706                         case CRP:       /* ')' in arithmetic */
10707                                 if (parenlevel > 0) {
10708                                         USTPUTC(c, out);
10709                                         --parenlevel;
10710                                 } else {
10711                                         if (pgetc() == ')') {
10712                                                 if (--arinest == 0) {
10713                                                         USTPUTC(CTLENDARI, out);
10714                                                         syntax = prevsyntax;
10715                                                         dblquote = (syntax == DQSYNTAX);
10716                                                 } else
10717                                                         USTPUTC(')', out);
10718                                         } else {
10719                                                 /*
10720                                                  * unbalanced parens
10721                                                  *  (don't 2nd guess - no error)
10722                                                  */
10723                                                 pungetc();
10724                                                 USTPUTC(')', out);
10725                                         }
10726                                 }
10727                                 break;
10728 #endif
10729                         case CBQUOTE:   /* '`' */
10730                                 PARSEBACKQOLD();
10731                                 break;
10732                         case CENDFILE:
10733                                 goto endword;           /* exit outer loop */
10734                         case CIGN:
10735                                 break;
10736                         default:
10737                                 if (varnest == 0)
10738                                         goto endword;   /* exit outer loop */
10739 #if ENABLE_ASH_ALIAS
10740                                 if (c != PEOA)
10741 #endif
10742                                         USTPUTC(c, out);
10743
10744                         }
10745                         c = pgetc_macro();
10746                 } /* for (;;) */
10747         }
10748  endword:
10749 #if ENABLE_ASH_MATH_SUPPORT
10750         if (syntax == ARISYNTAX)
10751                 raise_error_syntax("Missing '))'");
10752 #endif
10753         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10754                 raise_error_syntax("Unterminated quoted string");
10755         if (varnest != 0) {
10756                 startlinno = plinno;
10757                 /* { */
10758                 raise_error_syntax("Missing '}'");
10759         }
10760         USTPUTC('\0', out);
10761         len = out - (char *)stackblock();
10762         out = stackblock();
10763         if (eofmark == NULL) {
10764                 if ((c == '>' || c == '<') && quotef == 0) {
10765                         int maxlen = 9 + 1; /* max 9 digit fd#: 999999999 */
10766                         char *np = out;
10767                         while (--maxlen && isdigit(*np))
10768                                 np++;
10769                         if (*np == '\0') {
10770                                 PARSEREDIR(); /* passed as params: out, c */
10771                                 lasttoken = TREDIR;
10772                                 return lasttoken;
10773                         }
10774                         /* else: non-number X seen, interpret it
10775                          * as "NNNX>file" = "NNNX >file" */
10776                 }
10777                 pungetc();
10778         }
10779         quoteflag = quotef;
10780         backquotelist = bqlist;
10781         grabstackblock(len);
10782         wordtext = out;
10783         lasttoken = TWORD;
10784         return lasttoken;
10785 /* end of readtoken routine */
10786
10787 /*
10788  * Check to see whether we are at the end of the here document.  When this
10789  * is called, c is set to the first character of the next input line.  If
10790  * we are at the end of the here document, this routine sets the c to PEOF.
10791  */
10792 checkend: {
10793         if (eofmark) {
10794 #if ENABLE_ASH_ALIAS
10795                 if (c == PEOA) {
10796                         c = pgetc2();
10797                 }
10798 #endif
10799                 if (striptabs) {
10800                         while (c == '\t') {
10801                                 c = pgetc2();
10802                         }
10803                 }
10804                 if (c == *eofmark) {
10805                         if (pfgets(line, sizeof(line)) != NULL) {
10806                                 char *p, *q;
10807
10808                                 p = line;
10809                                 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10810                                         continue;
10811                                 if (*p == '\n' && *q == '\0') {
10812                                         c = PEOF;
10813                                         plinno++;
10814                                         needprompt = doprompt;
10815                                 } else {
10816                                         pushstring(line, NULL);
10817                                 }
10818                         }
10819                 }
10820         }
10821         goto checkend_return;
10822 }
10823
10824 /*
10825  * Parse a redirection operator.  The variable "out" points to a string
10826  * specifying the fd to be redirected.  The variable "c" contains the
10827  * first character of the redirection operator.
10828  */
10829 parseredir: {
10830         /* out is already checked to be a valid number or "" */
10831         int fd = (*out == '\0' ? -1 : atoi(out));
10832         union node *np;
10833
10834         np = stzalloc(sizeof(struct nfile));
10835         if (c == '>') {
10836                 np->nfile.fd = 1;
10837                 c = pgetc();
10838                 if (c == '>')
10839                         np->type = NAPPEND;
10840                 else if (c == '|')
10841                         np->type = NCLOBBER;
10842                 else if (c == '&')
10843                         np->type = NTOFD;
10844                 else {
10845                         np->type = NTO;
10846                         pungetc();
10847                 }
10848         } else {        /* c == '<' */
10849                 /*np->nfile.fd = 0; - stzalloc did it */
10850                 c = pgetc();
10851                 switch (c) {
10852                 case '<':
10853                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10854                                 np = stzalloc(sizeof(struct nhere));
10855                                 /*np->nfile.fd = 0; - stzalloc did it */
10856                         }
10857                         np->type = NHERE;
10858                         heredoc = stzalloc(sizeof(struct heredoc));
10859                         heredoc->here = np;
10860                         c = pgetc();
10861                         if (c == '-') {
10862                                 heredoc->striptabs = 1;
10863                         } else {
10864                                 /*heredoc->striptabs = 0; - stzalloc did it */
10865                                 pungetc();
10866                         }
10867                         break;
10868
10869                 case '&':
10870                         np->type = NFROMFD;
10871                         break;
10872
10873                 case '>':
10874                         np->type = NFROMTO;
10875                         break;
10876
10877                 default:
10878                         np->type = NFROM;
10879                         pungetc();
10880                         break;
10881                 }
10882         }
10883         if (fd >= 0)
10884                 np->nfile.fd = fd;
10885         redirnode = np;
10886         goto parseredir_return;
10887 }
10888
10889 /*
10890  * Parse a substitution.  At this point, we have read the dollar sign
10891  * and nothing else.
10892  */
10893
10894 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10895  * (assuming ascii char codes, as the original implementation did) */
10896 #define is_special(c) \
10897         (((unsigned)(c) - 33 < 32) \
10898                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10899 parsesub: {
10900         int subtype;
10901         int typeloc;
10902         int flags;
10903         char *p;
10904         static const char types[] ALIGN1 = "}-+?=";
10905
10906         c = pgetc();
10907         if (c <= PEOA_OR_PEOF
10908          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10909         ) {
10910 #if ENABLE_ASH_BASH_COMPAT
10911                 if (c == '\'')
10912                         bash_dollar_squote = 1;
10913                 else
10914 #endif
10915                         USTPUTC('$', out);
10916                 pungetc();
10917         } else if (c == '(') {  /* $(command) or $((arith)) */
10918                 if (pgetc() == '(') {
10919 #if ENABLE_ASH_MATH_SUPPORT
10920                         PARSEARITH();
10921 #else
10922                         raise_error_syntax("you disabled math support for $((arith)) syntax");
10923 #endif
10924                 } else {
10925                         pungetc();
10926                         PARSEBACKQNEW();
10927                 }
10928         } else {
10929                 USTPUTC(CTLVAR, out);
10930                 typeloc = out - (char *)stackblock();
10931                 USTPUTC(VSNORMAL, out);
10932                 subtype = VSNORMAL;
10933                 if (c == '{') {
10934                         c = pgetc();
10935                         if (c == '#') {
10936                                 c = pgetc();
10937                                 if (c == '}')
10938                                         c = '#';
10939                                 else
10940                                         subtype = VSLENGTH;
10941                         } else
10942                                 subtype = 0;
10943                 }
10944                 if (c > PEOA_OR_PEOF && is_name(c)) {
10945                         do {
10946                                 STPUTC(c, out);
10947                                 c = pgetc();
10948                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10949                 } else if (isdigit(c)) {
10950                         do {
10951                                 STPUTC(c, out);
10952                                 c = pgetc();
10953                         } while (isdigit(c));
10954                 } else if (is_special(c)) {
10955                         USTPUTC(c, out);
10956                         c = pgetc();
10957                 } else
10958  badsub:                raise_error_syntax("Bad substitution");
10959
10960                 STPUTC('=', out);
10961                 flags = 0;
10962                 if (subtype == 0) {
10963                         switch (c) {
10964                         case ':':
10965                                 c = pgetc();
10966 #if ENABLE_ASH_BASH_COMPAT
10967                                 if (c == ':' || c == '$' || isdigit(c)) {
10968                                         pungetc();
10969                                         subtype = VSSUBSTR;
10970                                         break;
10971                                 }
10972 #endif
10973                                 flags = VSNUL;
10974                                 /*FALLTHROUGH*/
10975                         default:
10976                                 p = strchr(types, c);
10977                                 if (p == NULL)
10978                                         goto badsub;
10979                                 subtype = p - types + VSNORMAL;
10980                                 break;
10981                         case '%':
10982                         case '#': {
10983                                 int cc = c;
10984                                 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10985                                 c = pgetc();
10986                                 if (c == cc)
10987                                         subtype++;
10988                                 else
10989                                         pungetc();
10990                                 break;
10991                         }
10992 #if ENABLE_ASH_BASH_COMPAT
10993                         case '/':
10994                                 subtype = VSREPLACE;
10995                                 c = pgetc();
10996                                 if (c == '/')
10997                                         subtype++; /* VSREPLACEALL */
10998                                 else
10999                                         pungetc();
11000                                 break;
11001 #endif
11002                         }
11003                 } else {
11004                         pungetc();
11005                 }
11006                 if (dblquote || arinest)
11007                         flags |= VSQUOTE;
11008                 *((char *)stackblock() + typeloc) = subtype | flags;
11009                 if (subtype != VSNORMAL) {
11010                         varnest++;
11011                         if (dblquote || arinest) {
11012                                 dqvarnest++;
11013                         }
11014                 }
11015         }
11016         goto parsesub_return;
11017 }
11018
11019 /*
11020  * Called to parse command substitutions.  Newstyle is set if the command
11021  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11022  * list of commands (passed by reference), and savelen is the number of
11023  * characters on the top of the stack which must be preserved.
11024  */
11025 parsebackq: {
11026         struct nodelist **nlpp;
11027         smallint savepbq;
11028         union node *n;
11029         char *volatile str;
11030         struct jmploc jmploc;
11031         struct jmploc *volatile savehandler;
11032         size_t savelen;
11033         smallint saveprompt = 0;
11034
11035 #ifdef __GNUC__
11036         (void) &saveprompt;
11037 #endif
11038         savepbq = parsebackquote;
11039         if (setjmp(jmploc.loc)) {
11040                 free(str);
11041                 parsebackquote = 0;
11042                 exception_handler = savehandler;
11043                 longjmp(exception_handler->loc, 1);
11044         }
11045         INT_OFF;
11046         str = NULL;
11047         savelen = out - (char *)stackblock();
11048         if (savelen > 0) {
11049                 str = ckmalloc(savelen);
11050                 memcpy(str, stackblock(), savelen);
11051         }
11052         savehandler = exception_handler;
11053         exception_handler = &jmploc;
11054         INT_ON;
11055         if (oldstyle) {
11056                 /* We must read until the closing backquote, giving special
11057                    treatment to some slashes, and then push the string and
11058                    reread it as input, interpreting it normally.  */
11059                 char *pout;
11060                 int pc;
11061                 size_t psavelen;
11062                 char *pstr;
11063
11064
11065                 STARTSTACKSTR(pout);
11066                 for (;;) {
11067                         if (needprompt) {
11068                                 setprompt(2);
11069                         }
11070                         pc = pgetc();
11071                         switch (pc) {
11072                         case '`':
11073                                 goto done;
11074
11075                         case '\\':
11076                                 pc = pgetc();
11077                                 if (pc == '\n') {
11078                                         plinno++;
11079                                         if (doprompt)
11080                                                 setprompt(2);
11081                                         /*
11082                                          * If eating a newline, avoid putting
11083                                          * the newline into the new character
11084                                          * stream (via the STPUTC after the
11085                                          * switch).
11086                                          */
11087                                         continue;
11088                                 }
11089                                 if (pc != '\\' && pc != '`' && pc != '$'
11090                                  && (!dblquote || pc != '"'))
11091                                         STPUTC('\\', pout);
11092                                 if (pc > PEOA_OR_PEOF) {
11093                                         break;
11094                                 }
11095                                 /* fall through */
11096
11097                         case PEOF:
11098 #if ENABLE_ASH_ALIAS
11099                         case PEOA:
11100 #endif
11101                                 startlinno = plinno;
11102                                 raise_error_syntax("EOF in backquote substitution");
11103
11104                         case '\n':
11105                                 plinno++;
11106                                 needprompt = doprompt;
11107                                 break;
11108
11109                         default:
11110                                 break;
11111                         }
11112                         STPUTC(pc, pout);
11113                 }
11114  done:
11115                 STPUTC('\0', pout);
11116                 psavelen = pout - (char *)stackblock();
11117                 if (psavelen > 0) {
11118                         pstr = grabstackstr(pout);
11119                         setinputstring(pstr);
11120                 }
11121         }
11122         nlpp = &bqlist;
11123         while (*nlpp)
11124                 nlpp = &(*nlpp)->next;
11125         *nlpp = stzalloc(sizeof(**nlpp));
11126         /* (*nlpp)->next = NULL; - stzalloc did it */
11127         parsebackquote = oldstyle;
11128
11129         if (oldstyle) {
11130                 saveprompt = doprompt;
11131                 doprompt = 0;
11132         }
11133
11134         n = list(2);
11135
11136         if (oldstyle)
11137                 doprompt = saveprompt;
11138         else if (readtoken() != TRP)
11139                 raise_error_unexpected_syntax(TRP);
11140
11141         (*nlpp)->n = n;
11142         if (oldstyle) {
11143                 /*
11144                  * Start reading from old file again, ignoring any pushed back
11145                  * tokens left from the backquote parsing
11146                  */
11147                 popfile();
11148                 tokpushback = 0;
11149         }
11150         while (stackblocksize() <= savelen)
11151                 growstackblock();
11152         STARTSTACKSTR(out);
11153         if (str) {
11154                 memcpy(out, str, savelen);
11155                 STADJUST(savelen, out);
11156                 INT_OFF;
11157                 free(str);
11158                 str = NULL;
11159                 INT_ON;
11160         }
11161         parsebackquote = savepbq;
11162         exception_handler = savehandler;
11163         if (arinest || dblquote)
11164                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11165         else
11166                 USTPUTC(CTLBACKQ, out);
11167         if (oldstyle)
11168                 goto parsebackq_oldreturn;
11169         goto parsebackq_newreturn;
11170 }
11171
11172 #if ENABLE_ASH_MATH_SUPPORT
11173 /*
11174  * Parse an arithmetic expansion (indicate start of one and set state)
11175  */
11176 parsearith: {
11177         if (++arinest == 1) {
11178                 prevsyntax = syntax;
11179                 syntax = ARISYNTAX;
11180                 USTPUTC(CTLARI, out);
11181                 if (dblquote)
11182                         USTPUTC('"', out);
11183                 else
11184                         USTPUTC(' ', out);
11185         } else {
11186                 /*
11187                  * we collapse embedded arithmetic expansion to
11188                  * parenthesis, which should be equivalent
11189                  */
11190                 USTPUTC('(', out);
11191         }
11192         goto parsearith_return;
11193 }
11194 #endif
11195
11196 } /* end of readtoken */
11197
11198 /*
11199  * Read the next input token.
11200  * If the token is a word, we set backquotelist to the list of cmds in
11201  *      backquotes.  We set quoteflag to true if any part of the word was
11202  *      quoted.
11203  * If the token is TREDIR, then we set redirnode to a structure containing
11204  *      the redirection.
11205  * In all cases, the variable startlinno is set to the number of the line
11206  *      on which the token starts.
11207  *
11208  * [Change comment:  here documents and internal procedures]
11209  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
11210  *  word parsing code into a separate routine.  In this case, readtoken
11211  *  doesn't need to have any internal procedures, but parseword does.
11212  *  We could also make parseoperator in essence the main routine, and
11213  *  have parseword (readtoken1?) handle both words and redirection.]
11214  */
11215 #define NEW_xxreadtoken
11216 #ifdef NEW_xxreadtoken
11217 /* singles must be first! */
11218 static const char xxreadtoken_chars[7] ALIGN1 = {
11219         '\n', '(', ')', '&', '|', ';', 0
11220 };
11221
11222 static const char xxreadtoken_tokens[] ALIGN1 = {
11223         TNL, TLP, TRP,          /* only single occurrence allowed */
11224         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11225         TEOF,                   /* corresponds to trailing nul */
11226         TAND, TOR, TENDCASE     /* if double occurrence */
11227 };
11228
11229 #define xxreadtoken_doubles \
11230         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
11231 #define xxreadtoken_singles \
11232         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
11233
11234 static int
11235 xxreadtoken(void)
11236 {
11237         int c;
11238
11239         if (tokpushback) {
11240                 tokpushback = 0;
11241                 return lasttoken;
11242         }
11243         if (needprompt) {
11244                 setprompt(2);
11245         }
11246         startlinno = plinno;
11247         for (;;) {                      /* until token or start of word found */
11248                 c = pgetc_macro();
11249
11250                 if ((c != ' ') && (c != '\t')
11251 #if ENABLE_ASH_ALIAS
11252                  && (c != PEOA)
11253 #endif
11254                 ) {
11255                         if (c == '#') {
11256                                 while ((c = pgetc()) != '\n' && c != PEOF)
11257                                         continue;
11258                                 pungetc();
11259                         } else if (c == '\\') {
11260                                 if (pgetc() != '\n') {
11261                                         pungetc();
11262                                         goto READTOKEN1;
11263                                 }
11264                                 startlinno = ++plinno;
11265                                 if (doprompt)
11266                                         setprompt(2);
11267                         } else {
11268                                 const char *p
11269                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11270
11271                                 if (c != PEOF) {
11272                                         if (c == '\n') {
11273                                                 plinno++;
11274                                                 needprompt = doprompt;
11275                                         }
11276
11277                                         p = strchr(xxreadtoken_chars, c);
11278                                         if (p == NULL) {
11279  READTOKEN1:
11280                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11281                                         }
11282
11283                                         if ((size_t)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11284                                                 if (pgetc() == *p) {    /* double occurrence? */
11285                                                         p += xxreadtoken_doubles + 1;
11286                                                 } else {
11287                                                         pungetc();
11288                                                 }
11289                                         }
11290                                 }
11291                                 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11292                                 return lasttoken;
11293                         }
11294                 }
11295         } /* for */
11296 }
11297 #else
11298 #define RETURN(token)   return lasttoken = token
11299 static int
11300 xxreadtoken(void)
11301 {
11302         int c;
11303
11304         if (tokpushback) {
11305                 tokpushback = 0;
11306                 return lasttoken;
11307         }
11308         if (needprompt) {
11309                 setprompt(2);
11310         }
11311         startlinno = plinno;
11312         for (;;) {      /* until token or start of word found */
11313                 c = pgetc_macro();
11314                 switch (c) {
11315                 case ' ': case '\t':
11316 #if ENABLE_ASH_ALIAS
11317                 case PEOA:
11318 #endif
11319                         continue;
11320                 case '#':
11321                         while ((c = pgetc()) != '\n' && c != PEOF)
11322                                 continue;
11323                         pungetc();
11324                         continue;
11325                 case '\\':
11326                         if (pgetc() == '\n') {
11327                                 startlinno = ++plinno;
11328                                 if (doprompt)
11329                                         setprompt(2);
11330                                 continue;
11331                         }
11332                         pungetc();
11333                         goto breakloop;
11334                 case '\n':
11335                         plinno++;
11336                         needprompt = doprompt;
11337                         RETURN(TNL);
11338                 case PEOF:
11339                         RETURN(TEOF);
11340                 case '&':
11341                         if (pgetc() == '&')
11342                                 RETURN(TAND);
11343                         pungetc();
11344                         RETURN(TBACKGND);
11345                 case '|':
11346                         if (pgetc() == '|')
11347                                 RETURN(TOR);
11348                         pungetc();
11349                         RETURN(TPIPE);
11350                 case ';':
11351                         if (pgetc() == ';')
11352                                 RETURN(TENDCASE);
11353                         pungetc();
11354                         RETURN(TSEMI);
11355                 case '(':
11356                         RETURN(TLP);
11357                 case ')':
11358                         RETURN(TRP);
11359                 default:
11360                         goto breakloop;
11361                 }
11362         }
11363  breakloop:
11364         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11365 #undef RETURN
11366 }
11367 #endif /* NEW_xxreadtoken */
11368
11369 static int
11370 readtoken(void)
11371 {
11372         int t;
11373 #if DEBUG
11374         smallint alreadyseen = tokpushback;
11375 #endif
11376
11377 #if ENABLE_ASH_ALIAS
11378  top:
11379 #endif
11380
11381         t = xxreadtoken();
11382
11383         /*
11384          * eat newlines
11385          */
11386         if (checkkwd & CHKNL) {
11387                 while (t == TNL) {
11388                         parseheredoc();
11389                         t = xxreadtoken();
11390                 }
11391         }
11392
11393         if (t != TWORD || quoteflag) {
11394                 goto out;
11395         }
11396
11397         /*
11398          * check for keywords
11399          */
11400         if (checkkwd & CHKKWD) {
11401                 const char *const *pp;
11402
11403                 pp = findkwd(wordtext);
11404                 if (pp) {
11405                         lasttoken = t = pp - tokname_array;
11406                         TRACE(("keyword %s recognized\n", tokname(t)));
11407                         goto out;
11408                 }
11409         }
11410
11411         if (checkkwd & CHKALIAS) {
11412 #if ENABLE_ASH_ALIAS
11413                 struct alias *ap;
11414                 ap = lookupalias(wordtext, 1);
11415                 if (ap != NULL) {
11416                         if (*ap->val) {
11417                                 pushstring(ap->val, ap);
11418                         }
11419                         goto top;
11420                 }
11421 #endif
11422         }
11423  out:
11424         checkkwd = 0;
11425 #if DEBUG
11426         if (!alreadyseen)
11427                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11428         else
11429                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11430 #endif
11431         return t;
11432 }
11433
11434 static char
11435 peektoken(void)
11436 {
11437         int t;
11438
11439         t = readtoken();
11440         tokpushback = 1;
11441         return tokname_array[t][0];
11442 }
11443
11444 /*
11445  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
11446  * valid parse tree indicating a blank line.)
11447  */
11448 static union node *
11449 parsecmd(int interact)
11450 {
11451         int t;
11452
11453         tokpushback = 0;
11454         doprompt = interact;
11455         if (doprompt)
11456                 setprompt(doprompt);
11457         needprompt = 0;
11458         t = readtoken();
11459         if (t == TEOF)
11460                 return NEOF;
11461         if (t == TNL)
11462                 return NULL;
11463         tokpushback = 1;
11464         return list(1);
11465 }
11466
11467 /*
11468  * Input any here documents.
11469  */
11470 static void
11471 parseheredoc(void)
11472 {
11473         struct heredoc *here;
11474         union node *n;
11475
11476         here = heredoclist;
11477         heredoclist = NULL;
11478
11479         while (here) {
11480                 if (needprompt) {
11481                         setprompt(2);
11482                 }
11483                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11484                                 here->eofmark, here->striptabs);
11485                 n = stzalloc(sizeof(struct narg));
11486                 n->narg.type = NARG;
11487                 /*n->narg.next = NULL; - stzalloc did it */
11488                 n->narg.text = wordtext;
11489                 n->narg.backquote = backquotelist;
11490                 here->here->nhere.doc = n;
11491                 here = here->next;
11492         }
11493 }
11494
11495
11496 /*
11497  * called by editline -- any expansions to the prompt should be added here.
11498  */
11499 #if ENABLE_ASH_EXPAND_PRMT
11500 static const char *
11501 expandstr(const char *ps)
11502 {
11503         union node n;
11504
11505         /* XXX Fix (char *) cast. */
11506         setinputstring((char *)ps);
11507         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11508         popfile();
11509
11510         n.narg.type = NARG;
11511         n.narg.next = NULL;
11512         n.narg.text = wordtext;
11513         n.narg.backquote = backquotelist;
11514
11515         expandarg(&n, NULL, 0);
11516         return stackblock();
11517 }
11518 #endif
11519
11520 /*
11521  * Execute a command or commands contained in a string.
11522  */
11523 static int
11524 evalstring(char *s, int mask)
11525 {
11526         union node *n;
11527         struct stackmark smark;
11528         int skip;
11529
11530         setinputstring(s);
11531         setstackmark(&smark);
11532
11533         skip = 0;
11534         while ((n = parsecmd(0)) != NEOF) {
11535                 evaltree(n, 0);
11536                 popstackmark(&smark);
11537                 skip = evalskip;
11538                 if (skip)
11539                         break;
11540         }
11541         popfile();
11542
11543         skip &= mask;
11544         evalskip = skip;
11545         return skip;
11546 }
11547
11548 /*
11549  * The eval command.
11550  */
11551 static int
11552 evalcmd(int argc UNUSED_PARAM, char **argv)
11553 {
11554         char *p;
11555         char *concat;
11556
11557         if (argv[1]) {
11558                 p = argv[1];
11559                 argv += 2;
11560                 if (argv[0]) {
11561                         STARTSTACKSTR(concat);
11562                         for (;;) {
11563                                 concat = stack_putstr(p, concat);
11564                                 p = *argv++;
11565                                 if (p == NULL)
11566                                         break;
11567                                 STPUTC(' ', concat);
11568                         }
11569                         STPUTC('\0', concat);
11570                         p = grabstackstr(concat);
11571                 }
11572                 evalstring(p, ~SKIPEVAL);
11573
11574         }
11575         return exitstatus;
11576 }
11577
11578 /*
11579  * Read and execute commands.  "Top" is nonzero for the top level command
11580  * loop; it turns on prompting if the shell is interactive.
11581  */
11582 static int
11583 cmdloop(int top)
11584 {
11585         union node *n;
11586         struct stackmark smark;
11587         int inter;
11588         int numeof = 0;
11589
11590         TRACE(("cmdloop(%d) called\n", top));
11591         for (;;) {
11592                 int skip;
11593
11594                 setstackmark(&smark);
11595 #if JOBS
11596                 if (doing_jobctl)
11597                         showjobs(stderr, SHOW_CHANGED);
11598 #endif
11599                 inter = 0;
11600                 if (iflag && top) {
11601                         inter++;
11602 #if ENABLE_ASH_MAIL
11603                         chkmail();
11604 #endif
11605                 }
11606                 n = parsecmd(inter);
11607                 /* showtree(n); DEBUG */
11608                 if (n == NEOF) {
11609                         if (!top || numeof >= 50)
11610                                 break;
11611                         if (!stoppedjobs()) {
11612                                 if (!Iflag)
11613                                         break;
11614                                 out2str("\nUse \"exit\" to leave shell.\n");
11615                         }
11616                         numeof++;
11617                 } else if (nflag == 0) {
11618                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11619                         job_warning >>= 1;
11620                         numeof = 0;
11621                         evaltree(n, 0);
11622                 }
11623                 popstackmark(&smark);
11624                 skip = evalskip;
11625
11626                 if (skip) {
11627                         evalskip = 0;
11628                         return skip & SKIPEVAL;
11629                 }
11630         }
11631         return 0;
11632 }
11633
11634 /*
11635  * Take commands from a file.  To be compatible we should do a path
11636  * search for the file, which is necessary to find sub-commands.
11637  */
11638 static char *
11639 find_dot_file(char *name)
11640 {
11641         char *fullname;
11642         const char *path = pathval();
11643         struct stat statb;
11644
11645         /* don't try this for absolute or relative paths */
11646         if (strchr(name, '/'))
11647                 return name;
11648
11649         while ((fullname = padvance(&path, name)) != NULL) {
11650                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11651                         /*
11652                          * Don't bother freeing here, since it will
11653                          * be freed by the caller.
11654                          */
11655                         return fullname;
11656                 }
11657                 stunalloc(fullname);
11658         }
11659
11660         /* not found in the PATH */
11661         ash_msg_and_raise_error("%s: not found", name);
11662         /* NOTREACHED */
11663 }
11664
11665 static int
11666 dotcmd(int argc, char **argv)
11667 {
11668         struct strlist *sp;
11669         volatile struct shparam saveparam;
11670         int status = 0;
11671
11672         for (sp = cmdenviron; sp; sp = sp->next)
11673                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11674
11675         if (argv[1]) {        /* That's what SVR2 does */
11676                 char *fullname = find_dot_file(argv[1]);
11677                 argv += 2;
11678                 argc -= 2;
11679                 if (argc) { /* argc > 0, argv[0] != NULL */
11680                         saveparam = shellparam;
11681                         shellparam.malloced = 0;
11682                         shellparam.nparam = argc;
11683                         shellparam.p = argv;
11684                 };
11685
11686                 setinputfile(fullname, INPUT_PUSH_FILE);
11687                 commandname = fullname;
11688                 cmdloop(0);
11689                 popfile();
11690
11691                 if (argc) {
11692                         freeparam(&shellparam);
11693                         shellparam = saveparam;
11694                 };
11695                 status = exitstatus;
11696         }
11697         return status;
11698 }
11699
11700 static int
11701 exitcmd(int argc UNUSED_PARAM, char **argv)
11702 {
11703         if (stoppedjobs())
11704                 return 0;
11705         if (argv[1])
11706                 exitstatus = number(argv[1]);
11707         raise_exception(EXEXIT);
11708         /* NOTREACHED */
11709 }
11710
11711 /*
11712  * Read a file containing shell functions.
11713  */
11714 static void
11715 readcmdfile(char *name)
11716 {
11717         setinputfile(name, INPUT_PUSH_FILE);
11718         cmdloop(0);
11719         popfile();
11720 }
11721
11722
11723 /* ============ find_command inplementation */
11724
11725 /*
11726  * Resolve a command name.  If you change this routine, you may have to
11727  * change the shellexec routine as well.
11728  */
11729 static void
11730 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11731 {
11732         struct tblentry *cmdp;
11733         int idx;
11734         int prev;
11735         char *fullname;
11736         struct stat statb;
11737         int e;
11738         int updatetbl;
11739         struct builtincmd *bcmd;
11740
11741         /* If name contains a slash, don't use PATH or hash table */
11742         if (strchr(name, '/') != NULL) {
11743                 entry->u.index = -1;
11744                 if (act & DO_ABS) {
11745                         while (stat(name, &statb) < 0) {
11746 #ifdef SYSV
11747                                 if (errno == EINTR)
11748                                         continue;
11749 #endif
11750                                 entry->cmdtype = CMDUNKNOWN;
11751                                 return;
11752                         }
11753                 }
11754                 entry->cmdtype = CMDNORMAL;
11755                 return;
11756         }
11757
11758 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11759
11760         updatetbl = (path == pathval());
11761         if (!updatetbl) {
11762                 act |= DO_ALTPATH;
11763                 if (strstr(path, "%builtin") != NULL)
11764                         act |= DO_ALTBLTIN;
11765         }
11766
11767         /* If name is in the table, check answer will be ok */
11768         cmdp = cmdlookup(name, 0);
11769         if (cmdp != NULL) {
11770                 int bit;
11771
11772                 switch (cmdp->cmdtype) {
11773                 default:
11774 #if DEBUG
11775                         abort();
11776 #endif
11777                 case CMDNORMAL:
11778                         bit = DO_ALTPATH;
11779                         break;
11780                 case CMDFUNCTION:
11781                         bit = DO_NOFUNC;
11782                         break;
11783                 case CMDBUILTIN:
11784                         bit = DO_ALTBLTIN;
11785                         break;
11786                 }
11787                 if (act & bit) {
11788                         updatetbl = 0;
11789                         cmdp = NULL;
11790                 } else if (cmdp->rehash == 0)
11791                         /* if not invalidated by cd, we're done */
11792                         goto success;
11793         }
11794
11795         /* If %builtin not in path, check for builtin next */
11796         bcmd = find_builtin(name);
11797         if (bcmd) {
11798                 if (IS_BUILTIN_REGULAR(bcmd))
11799                         goto builtin_success;
11800                 if (act & DO_ALTPATH) {
11801                         if (!(act & DO_ALTBLTIN))
11802                                 goto builtin_success;
11803                 } else if (builtinloc <= 0) {
11804                         goto builtin_success;
11805                 }
11806         }
11807
11808 #if ENABLE_FEATURE_SH_STANDALONE
11809         {
11810                 int applet_no = find_applet_by_name(name);
11811                 if (applet_no >= 0) {
11812                         entry->cmdtype = CMDNORMAL;
11813                         entry->u.index = -2 - applet_no;
11814                         return;
11815                 }
11816         }
11817 #endif
11818
11819         /* We have to search path. */
11820         prev = -1;              /* where to start */
11821         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11822                 if (cmdp->cmdtype == CMDBUILTIN)
11823                         prev = builtinloc;
11824                 else
11825                         prev = cmdp->param.index;
11826         }
11827
11828         e = ENOENT;
11829         idx = -1;
11830  loop:
11831         while ((fullname = padvance(&path, name)) != NULL) {
11832                 stunalloc(fullname);
11833                 /* NB: code below will still use fullname
11834                  * despite it being "unallocated" */
11835                 idx++;
11836                 if (pathopt) {
11837                         if (prefix(pathopt, "builtin")) {
11838                                 if (bcmd)
11839                                         goto builtin_success;
11840                                 continue;
11841                         }
11842                         if ((act & DO_NOFUNC)
11843                          || !prefix(pathopt, "func")
11844                         ) {     /* ignore unimplemented options */
11845                                 continue;
11846                         }
11847                 }
11848                 /* if rehash, don't redo absolute path names */
11849                 if (fullname[0] == '/' && idx <= prev) {
11850                         if (idx < prev)
11851                                 continue;
11852                         TRACE(("searchexec \"%s\": no change\n", name));
11853                         goto success;
11854                 }
11855                 while (stat(fullname, &statb) < 0) {
11856 #ifdef SYSV
11857                         if (errno == EINTR)
11858                                 continue;
11859 #endif
11860                         if (errno != ENOENT && errno != ENOTDIR)
11861                                 e = errno;
11862                         goto loop;
11863                 }
11864                 e = EACCES;     /* if we fail, this will be the error */
11865                 if (!S_ISREG(statb.st_mode))
11866                         continue;
11867                 if (pathopt) {          /* this is a %func directory */
11868                         stalloc(strlen(fullname) + 1);
11869                         /* NB: stalloc will return space pointed by fullname
11870                          * (because we don't have any intervening allocations
11871                          * between stunalloc above and this stalloc) */
11872                         readcmdfile(fullname);
11873                         cmdp = cmdlookup(name, 0);
11874                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11875                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11876                         stunalloc(fullname);
11877                         goto success;
11878                 }
11879                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11880                 if (!updatetbl) {
11881                         entry->cmdtype = CMDNORMAL;
11882                         entry->u.index = idx;
11883                         return;
11884                 }
11885                 INT_OFF;
11886                 cmdp = cmdlookup(name, 1);
11887                 cmdp->cmdtype = CMDNORMAL;
11888                 cmdp->param.index = idx;
11889                 INT_ON;
11890                 goto success;
11891         }
11892
11893         /* We failed.  If there was an entry for this command, delete it */
11894         if (cmdp && updatetbl)
11895                 delete_cmd_entry();
11896         if (act & DO_ERR)
11897                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11898         entry->cmdtype = CMDUNKNOWN;
11899         return;
11900
11901  builtin_success:
11902         if (!updatetbl) {
11903                 entry->cmdtype = CMDBUILTIN;
11904                 entry->u.cmd = bcmd;
11905                 return;
11906         }
11907         INT_OFF;
11908         cmdp = cmdlookup(name, 1);
11909         cmdp->cmdtype = CMDBUILTIN;
11910         cmdp->param.cmd = bcmd;
11911         INT_ON;
11912  success:
11913         cmdp->rehash = 0;
11914         entry->cmdtype = cmdp->cmdtype;
11915         entry->u = cmdp->param;
11916 }
11917
11918
11919 /* ============ trap.c */
11920
11921 /*
11922  * The trap builtin.
11923  */
11924 static int
11925 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11926 {
11927         char *action;
11928         char **ap;
11929         int signo;
11930
11931         nextopt(nullstr);
11932         ap = argptr;
11933         if (!*ap) {
11934                 for (signo = 0; signo < NSIG; signo++) {
11935                         if (trap[signo] != NULL) {
11936                                 out1fmt("trap -- %s %s\n",
11937                                                 single_quote(trap[signo]),
11938                                                 get_signame(signo));
11939                         }
11940                 }
11941                 return 0;
11942         }
11943         action = NULL;
11944         if (ap[1])
11945                 action = *ap++;
11946         while (*ap) {
11947                 signo = get_signum(*ap);
11948                 if (signo < 0)
11949                         ash_msg_and_raise_error("%s: bad trap", *ap);
11950                 INT_OFF;
11951                 if (action) {
11952                         if (LONE_DASH(action))
11953                                 action = NULL;
11954                         else
11955                                 action = ckstrdup(action);
11956                 }
11957                 free(trap[signo]);
11958                 trap[signo] = action;
11959                 if (signo != 0)
11960                         setsignal(signo);
11961                 INT_ON;
11962                 ap++;
11963         }
11964         return 0;
11965 }
11966
11967
11968 /* ============ Builtins */
11969
11970 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11971 /*
11972  * Lists available builtins
11973  */
11974 static int
11975 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11976 {
11977         unsigned col;
11978         unsigned i;
11979
11980         out1fmt("\nBuilt-in commands:\n-------------------\n");
11981         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11982                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11983                                         builtintab[i].name + 1);
11984                 if (col > 60) {
11985                         out1fmt("\n");
11986                         col = 0;
11987                 }
11988         }
11989 #if ENABLE_FEATURE_SH_STANDALONE
11990         {
11991                 const char *a = applet_names;
11992                 while (*a) {
11993                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11994                         if (col > 60) {
11995                                 out1fmt("\n");
11996                                 col = 0;
11997                         }
11998                         a += strlen(a) + 1;
11999                 }
12000         }
12001 #endif
12002         out1fmt("\n\n");
12003         return EXIT_SUCCESS;
12004 }
12005 #endif /* FEATURE_SH_EXTRA_QUIET */
12006
12007 /*
12008  * The export and readonly commands.
12009  */
12010 static int
12011 exportcmd(int argc UNUSED_PARAM, char **argv)
12012 {
12013         struct var *vp;
12014         char *name;
12015         const char *p;
12016         char **aptr;
12017         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12018
12019         if (nextopt("p") != 'p') {
12020                 aptr = argptr;
12021                 name = *aptr;
12022                 if (name) {
12023                         do {
12024                                 p = strchr(name, '=');
12025                                 if (p != NULL) {
12026                                         p++;
12027                                 } else {
12028                                         vp = *findvar(hashvar(name), name);
12029                                         if (vp) {
12030                                                 vp->flags |= flag;
12031                                                 continue;
12032                                         }
12033                                 }
12034                                 setvar(name, p, flag);
12035                         } while ((name = *++aptr) != NULL);
12036                         return 0;
12037                 }
12038         }
12039         showvars(argv[0], flag, 0);
12040         return 0;
12041 }
12042
12043 /*
12044  * Delete a function if it exists.
12045  */
12046 static void
12047 unsetfunc(const char *name)
12048 {
12049         struct tblentry *cmdp;
12050
12051         cmdp = cmdlookup(name, 0);
12052         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12053                 delete_cmd_entry();
12054 }
12055
12056 /*
12057  * The unset builtin command.  We unset the function before we unset the
12058  * variable to allow a function to be unset when there is a readonly variable
12059  * with the same name.
12060  */
12061 static int
12062 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12063 {
12064         char **ap;
12065         int i;
12066         int flag = 0;
12067         int ret = 0;
12068
12069         while ((i = nextopt("vf")) != '\0') {
12070                 flag = i;
12071         }
12072
12073         for (ap = argptr; *ap; ap++) {
12074                 if (flag != 'f') {
12075                         i = unsetvar(*ap);
12076                         ret |= i;
12077                         if (!(i & 2))
12078                                 continue;
12079                 }
12080                 if (flag != 'v')
12081                         unsetfunc(*ap);
12082         }
12083         return ret & 1;
12084 }
12085
12086
12087 /*      setmode.c      */
12088
12089 #include <sys/times.h>
12090
12091 static const unsigned char timescmd_str[] ALIGN1 = {
12092         ' ',  offsetof(struct tms, tms_utime),
12093         '\n', offsetof(struct tms, tms_stime),
12094         ' ',  offsetof(struct tms, tms_cutime),
12095         '\n', offsetof(struct tms, tms_cstime),
12096         0
12097 };
12098
12099 static int
12100 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12101 {
12102         long clk_tck, s, t;
12103         const unsigned char *p;
12104         struct tms buf;
12105
12106         clk_tck = sysconf(_SC_CLK_TCK);
12107         times(&buf);
12108
12109         p = timescmd_str;
12110         do {
12111                 t = *(clock_t *)(((char *) &buf) + p[1]);
12112                 s = t / clk_tck;
12113                 out1fmt("%ldm%ld.%.3lds%c",
12114                         s/60, s%60,
12115                         ((t - s * clk_tck) * 1000) / clk_tck,
12116                         p[0]);
12117         } while (*(p += 2));
12118
12119         return 0;
12120 }
12121
12122 #if ENABLE_ASH_MATH_SUPPORT
12123 static arith_t
12124 dash_arith(const char *s)
12125 {
12126         arith_t result;
12127         int errcode = 0;
12128
12129         INT_OFF;
12130         result = arith(s, &errcode);
12131         if (errcode < 0) {
12132                 if (errcode == -3)
12133                         ash_msg_and_raise_error("exponent less than 0");
12134                 if (errcode == -2)
12135                         ash_msg_and_raise_error("divide by zero");
12136                 if (errcode == -5)
12137                         ash_msg_and_raise_error("expression recursion loop detected");
12138                 raise_error_syntax(s);
12139         }
12140         INT_ON;
12141
12142         return result;
12143 }
12144
12145 /*
12146  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12147  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12148  *
12149  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12150  */
12151 static int
12152 letcmd(int argc UNUSED_PARAM, char **argv)
12153 {
12154         arith_t i;
12155
12156         argv++;
12157         if (!*argv)
12158                 ash_msg_and_raise_error("expression expected");
12159         do {
12160                 i = dash_arith(*argv);
12161         } while (*++argv);
12162
12163         return !i;
12164 }
12165 #endif /* ASH_MATH_SUPPORT */
12166
12167
12168 /* ============ miscbltin.c
12169  *
12170  * Miscellaneous builtins.
12171  */
12172
12173 #undef rflag
12174
12175 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12176 typedef enum __rlimit_resource rlim_t;
12177 #endif
12178
12179 /*
12180  * The read builtin. Options:
12181  *      -r              Do not interpret '\' specially
12182  *      -s              Turn off echo (tty only)
12183  *      -n NCHARS       Read NCHARS max
12184  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12185  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12186  *      -u FD           Read from given FD instead of fd 0
12187  * This uses unbuffered input, which may be avoidable in some cases.
12188  * TODO: bash also has:
12189  *      -a ARRAY        Read into array[0],[1],etc
12190  *      -d DELIM        End on DELIM char, not newline
12191  *      -e              Use line editing (tty only)
12192  */
12193 static int
12194 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12195 {
12196         static const char *const arg_REPLY[] = { "REPLY", NULL };
12197
12198         char **ap;
12199         int backslash;
12200         char c;
12201         int rflag;
12202         char *prompt;
12203         const char *ifs;
12204         char *p;
12205         int startword;
12206         int status;
12207         int i;
12208         int fd = 0;
12209 #if ENABLE_ASH_READ_NCHARS
12210         int nchars = 0; /* if != 0, -n is in effect */
12211         int silent = 0;
12212         struct termios tty, old_tty;
12213 #endif
12214 #if ENABLE_ASH_READ_TIMEOUT
12215         unsigned end_ms = 0;
12216         unsigned timeout = 0;
12217 #endif
12218
12219         rflag = 0;
12220         prompt = NULL;
12221         while ((i = nextopt("p:u:r"
12222                 USE_ASH_READ_TIMEOUT("t:")
12223                 USE_ASH_READ_NCHARS("n:s")
12224         )) != '\0') {
12225                 switch (i) {
12226                 case 'p':
12227                         prompt = optionarg;
12228                         break;
12229 #if ENABLE_ASH_READ_NCHARS
12230                 case 'n':
12231                         nchars = bb_strtou(optionarg, NULL, 10);
12232                         if (nchars < 0 || errno)
12233                                 ash_msg_and_raise_error("invalid count");
12234                         /* nchars == 0: off (bash 3.2 does this too) */
12235                         break;
12236                 case 's':
12237                         silent = 1;
12238                         break;
12239 #endif
12240 #if ENABLE_ASH_READ_TIMEOUT
12241                 case 't':
12242                         timeout = bb_strtou(optionarg, NULL, 10);
12243                         if (errno || timeout > UINT_MAX / 2048)
12244                                 ash_msg_and_raise_error("invalid timeout");
12245                         timeout *= 1000;
12246 #if 0 /* even bash have no -t N.NNN support */
12247                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
12248                         ts.tv_usec = 0;
12249                         /* EINVAL means number is ok, but not terminated by NUL */
12250                         if (*p == '.' && errno == EINVAL) {
12251                                 char *p2;
12252                                 if (*++p) {
12253                                         int scale;
12254                                         ts.tv_usec = bb_strtou(p, &p2, 10);
12255                                         if (errno)
12256                                                 ash_msg_and_raise_error("invalid timeout");
12257                                         scale = p2 - p;
12258                                         /* normalize to usec */
12259                                         if (scale > 6)
12260                                                 ash_msg_and_raise_error("invalid timeout");
12261                                         while (scale++ < 6)
12262                                                 ts.tv_usec *= 10;
12263                                 }
12264                         } else if (ts.tv_sec < 0 || errno) {
12265                                 ash_msg_and_raise_error("invalid timeout");
12266                         }
12267                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12268                                 ash_msg_and_raise_error("invalid timeout");
12269                         }
12270 #endif /* if 0 */
12271                         break;
12272 #endif
12273                 case 'r':
12274                         rflag = 1;
12275                         break;
12276                 case 'u':
12277                         fd = bb_strtou(optionarg, NULL, 10);
12278                         if (fd < 0 || errno)
12279                                 ash_msg_and_raise_error("invalid file descriptor");
12280                         break;
12281                 default:
12282                         break;
12283                 }
12284         }
12285         if (prompt && isatty(fd)) {
12286                 out2str(prompt);
12287         }
12288         ap = argptr;
12289         if (*ap == NULL)
12290                 ap = (char**)arg_REPLY;
12291         ifs = bltinlookup("IFS");
12292         if (ifs == NULL)
12293                 ifs = defifs;
12294 #if ENABLE_ASH_READ_NCHARS
12295         tcgetattr(fd, &tty);
12296         old_tty = tty;
12297         if (nchars || silent) {
12298                 if (nchars) {
12299                         tty.c_lflag &= ~ICANON;
12300                         tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12301                 }
12302                 if (silent) {
12303                         tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12304                 }
12305                 /* if tcgetattr failed, tcsetattr will fail too.
12306                  * Ignoring, it's harmless. */
12307                 tcsetattr(fd, TCSANOW, &tty);
12308         }
12309 #endif
12310
12311         status = 0;
12312         startword = 1;
12313         backslash = 0;
12314 #if ENABLE_ASH_READ_TIMEOUT
12315         if (timeout) /* NB: ensuring end_ms is nonzero */
12316                 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12317 #endif
12318         STARTSTACKSTR(p);
12319         do {
12320 #if ENABLE_ASH_READ_TIMEOUT
12321                 if (end_ms) {
12322                         struct pollfd pfd[1];
12323                         pfd[0].fd = fd;
12324                         pfd[0].events = POLLIN;
12325                         timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12326                         if ((int)timeout <= 0 /* already late? */
12327                          || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12328                         ) { /* timed out! */
12329 #if ENABLE_ASH_READ_NCHARS
12330                                 tcsetattr(fd, TCSANOW, &old_tty);
12331 #endif
12332                                 return 1;
12333                         }
12334                 }
12335 #endif
12336                 if (nonblock_safe_read(fd, &c, 1) != 1) {
12337                         status = 1;
12338                         break;
12339                 }
12340                 if (c == '\0')
12341                         continue;
12342                 if (backslash) {
12343                         backslash = 0;
12344                         if (c != '\n')
12345                                 goto put;
12346                         continue;
12347                 }
12348                 if (!rflag && c == '\\') {
12349                         backslash++;
12350                         continue;
12351                 }
12352                 if (c == '\n')
12353                         break;
12354                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12355                         continue;
12356                 }
12357                 startword = 0;
12358                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12359                         STACKSTRNUL(p);
12360                         setvar(*ap, stackblock(), 0);
12361                         ap++;
12362                         startword = 1;
12363                         STARTSTACKSTR(p);
12364                 } else {
12365  put:
12366                         STPUTC(c, p);
12367                 }
12368         }
12369 /* end of do {} while: */
12370 #if ENABLE_ASH_READ_NCHARS
12371         while (--nchars);
12372 #else
12373         while (1);
12374 #endif
12375
12376 #if ENABLE_ASH_READ_NCHARS
12377         tcsetattr(fd, TCSANOW, &old_tty);
12378 #endif
12379
12380         STACKSTRNUL(p);
12381         /* Remove trailing blanks */
12382         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12383                 *p = '\0';
12384         setvar(*ap, stackblock(), 0);
12385         while (*++ap != NULL)
12386                 setvar(*ap, nullstr, 0);
12387         return status;
12388 }
12389
12390 static int
12391 umaskcmd(int argc UNUSED_PARAM, char **argv)
12392 {
12393         static const char permuser[3] ALIGN1 = "ugo";
12394         static const char permmode[3] ALIGN1 = "rwx";
12395         static const short permmask[] ALIGN2 = {
12396                 S_IRUSR, S_IWUSR, S_IXUSR,
12397                 S_IRGRP, S_IWGRP, S_IXGRP,
12398                 S_IROTH, S_IWOTH, S_IXOTH
12399         };
12400
12401         char *ap;
12402         mode_t mask;
12403         int i;
12404         int symbolic_mode = 0;
12405
12406         while (nextopt("S") != '\0') {
12407                 symbolic_mode = 1;
12408         }
12409
12410         INT_OFF;
12411         mask = umask(0);
12412         umask(mask);
12413         INT_ON;
12414
12415         ap = *argptr;
12416         if (ap == NULL) {
12417                 if (symbolic_mode) {
12418                         char buf[18];
12419                         char *p = buf;
12420
12421                         for (i = 0; i < 3; i++) {
12422                                 int j;
12423
12424                                 *p++ = permuser[i];
12425                                 *p++ = '=';
12426                                 for (j = 0; j < 3; j++) {
12427                                         if ((mask & permmask[3 * i + j]) == 0) {
12428                                                 *p++ = permmode[j];
12429                                         }
12430                                 }
12431                                 *p++ = ',';
12432                         }
12433                         *--p = 0;
12434                         puts(buf);
12435                 } else {
12436                         out1fmt("%.4o\n", mask);
12437                 }
12438         } else {
12439                 if (isdigit((unsigned char) *ap)) {
12440                         mask = 0;
12441                         do {
12442                                 if (*ap >= '8' || *ap < '0')
12443                                         ash_msg_and_raise_error(illnum, argv[1]);
12444                                 mask = (mask << 3) + (*ap - '0');
12445                         } while (*++ap != '\0');
12446                         umask(mask);
12447                 } else {
12448                         mask = ~mask & 0777;
12449                         if (!bb_parse_mode(ap, &mask)) {
12450                                 ash_msg_and_raise_error("illegal mode: %s", ap);
12451                         }
12452                         umask(~mask & 0777);
12453                 }
12454         }
12455         return 0;
12456 }
12457
12458 /*
12459  * ulimit builtin
12460  *
12461  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12462  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12463  * ash by J.T. Conklin.
12464  *
12465  * Public domain.
12466  */
12467
12468 struct limits {
12469         uint8_t cmd;          /* RLIMIT_xxx fit into it */
12470         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12471         char    option;
12472 };
12473
12474 static const struct limits limits_tbl[] = {
12475 #ifdef RLIMIT_CPU
12476         { RLIMIT_CPU,        0, 't' },
12477 #endif
12478 #ifdef RLIMIT_FSIZE
12479         { RLIMIT_FSIZE,      9, 'f' },
12480 #endif
12481 #ifdef RLIMIT_DATA
12482         { RLIMIT_DATA,      10, 'd' },
12483 #endif
12484 #ifdef RLIMIT_STACK
12485         { RLIMIT_STACK,     10, 's' },
12486 #endif
12487 #ifdef RLIMIT_CORE
12488         { RLIMIT_CORE,       9, 'c' },
12489 #endif
12490 #ifdef RLIMIT_RSS
12491         { RLIMIT_RSS,       10, 'm' },
12492 #endif
12493 #ifdef RLIMIT_MEMLOCK
12494         { RLIMIT_MEMLOCK,   10, 'l' },
12495 #endif
12496 #ifdef RLIMIT_NPROC
12497         { RLIMIT_NPROC,      0, 'p' },
12498 #endif
12499 #ifdef RLIMIT_NOFILE
12500         { RLIMIT_NOFILE,     0, 'n' },
12501 #endif
12502 #ifdef RLIMIT_AS
12503         { RLIMIT_AS,        10, 'v' },
12504 #endif
12505 #ifdef RLIMIT_LOCKS
12506         { RLIMIT_LOCKS,      0, 'w' },
12507 #endif
12508 };
12509 static const char limits_name[] =
12510 #ifdef RLIMIT_CPU
12511         "time(seconds)" "\0"
12512 #endif
12513 #ifdef RLIMIT_FSIZE
12514         "file(blocks)" "\0"
12515 #endif
12516 #ifdef RLIMIT_DATA
12517         "data(kb)" "\0"
12518 #endif
12519 #ifdef RLIMIT_STACK
12520         "stack(kb)" "\0"
12521 #endif
12522 #ifdef RLIMIT_CORE
12523         "coredump(blocks)" "\0"
12524 #endif
12525 #ifdef RLIMIT_RSS
12526         "memory(kb)" "\0"
12527 #endif
12528 #ifdef RLIMIT_MEMLOCK
12529         "locked memory(kb)" "\0"
12530 #endif
12531 #ifdef RLIMIT_NPROC
12532         "process" "\0"
12533 #endif
12534 #ifdef RLIMIT_NOFILE
12535         "nofiles" "\0"
12536 #endif
12537 #ifdef RLIMIT_AS
12538         "vmemory(kb)" "\0"
12539 #endif
12540 #ifdef RLIMIT_LOCKS
12541         "locks" "\0"
12542 #endif
12543 ;
12544
12545 enum limtype { SOFT = 0x1, HARD = 0x2 };
12546
12547 static void
12548 printlim(enum limtype how, const struct rlimit *limit,
12549                         const struct limits *l)
12550 {
12551         rlim_t val;
12552
12553         val = limit->rlim_max;
12554         if (how & SOFT)
12555                 val = limit->rlim_cur;
12556
12557         if (val == RLIM_INFINITY)
12558                 out1fmt("unlimited\n");
12559         else {
12560                 val >>= l->factor_shift;
12561                 out1fmt("%lld\n", (long long) val);
12562         }
12563 }
12564
12565 static int
12566 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12567 {
12568         int c;
12569         rlim_t val = 0;
12570         enum limtype how = SOFT | HARD;
12571         const struct limits *l;
12572         int set, all = 0;
12573         int optc, what;
12574         struct rlimit limit;
12575
12576         what = 'f';
12577         while ((optc = nextopt("HSa"
12578 #ifdef RLIMIT_CPU
12579                                 "t"
12580 #endif
12581 #ifdef RLIMIT_FSIZE
12582                                 "f"
12583 #endif
12584 #ifdef RLIMIT_DATA
12585                                 "d"
12586 #endif
12587 #ifdef RLIMIT_STACK
12588                                 "s"
12589 #endif
12590 #ifdef RLIMIT_CORE
12591                                 "c"
12592 #endif
12593 #ifdef RLIMIT_RSS
12594                                 "m"
12595 #endif
12596 #ifdef RLIMIT_MEMLOCK
12597                                 "l"
12598 #endif
12599 #ifdef RLIMIT_NPROC
12600                                 "p"
12601 #endif
12602 #ifdef RLIMIT_NOFILE
12603                                 "n"
12604 #endif
12605 #ifdef RLIMIT_AS
12606                                 "v"
12607 #endif
12608 #ifdef RLIMIT_LOCKS
12609                                 "w"
12610 #endif
12611                                         )) != '\0')
12612                 switch (optc) {
12613                 case 'H':
12614                         how = HARD;
12615                         break;
12616                 case 'S':
12617                         how = SOFT;
12618                         break;
12619                 case 'a':
12620                         all = 1;
12621                         break;
12622                 default:
12623                         what = optc;
12624                 }
12625
12626         for (l = limits_tbl; l->option != what; l++)
12627                 continue;
12628
12629         set = *argptr ? 1 : 0;
12630         if (set) {
12631                 char *p = *argptr;
12632
12633                 if (all || argptr[1])
12634                         ash_msg_and_raise_error("too many arguments");
12635                 if (strncmp(p, "unlimited\n", 9) == 0)
12636                         val = RLIM_INFINITY;
12637                 else {
12638                         val = (rlim_t) 0;
12639
12640                         while ((c = *p++) >= '0' && c <= '9') {
12641                                 val = (val * 10) + (long)(c - '0');
12642                                 // val is actually 'unsigned long int' and can't get < 0
12643                                 if (val < (rlim_t) 0)
12644                                         break;
12645                         }
12646                         if (c)
12647                                 ash_msg_and_raise_error("bad number");
12648                         val <<= l->factor_shift;
12649                 }
12650         }
12651         if (all) {
12652                 const char *lname = limits_name;
12653                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12654                         getrlimit(l->cmd, &limit);
12655                         out1fmt("%-20s ", lname);
12656                         lname += strlen(lname) + 1;
12657                         printlim(how, &limit, l);
12658                 }
12659                 return 0;
12660         }
12661
12662         getrlimit(l->cmd, &limit);
12663         if (set) {
12664                 if (how & HARD)
12665                         limit.rlim_max = val;
12666                 if (how & SOFT)
12667                         limit.rlim_cur = val;
12668                 if (setrlimit(l->cmd, &limit) < 0)
12669                         ash_msg_and_raise_error("error setting limit (%m)");
12670         } else {
12671                 printlim(how, &limit, l);
12672         }
12673         return 0;
12674 }
12675
12676
12677 /* ============ Math support */
12678
12679 #if ENABLE_ASH_MATH_SUPPORT
12680
12681 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12682
12683    Permission is hereby granted, free of charge, to any person obtaining
12684    a copy of this software and associated documentation files (the
12685    "Software"), to deal in the Software without restriction, including
12686    without limitation the rights to use, copy, modify, merge, publish,
12687    distribute, sublicense, and/or sell copies of the Software, and to
12688    permit persons to whom the Software is furnished to do so, subject to
12689    the following conditions:
12690
12691    The above copyright notice and this permission notice shall be
12692    included in all copies or substantial portions of the Software.
12693
12694    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12695    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12696    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12697    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12698    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12699    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12700    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12701 */
12702
12703 /* This is my infix parser/evaluator. It is optimized for size, intended
12704  * as a replacement for yacc-based parsers. However, it may well be faster
12705  * than a comparable parser written in yacc. The supported operators are
12706  * listed in #defines below. Parens, order of operations, and error handling
12707  * are supported. This code is thread safe. The exact expression format should
12708  * be that which POSIX specifies for shells. */
12709
12710 /* The code uses a simple two-stack algorithm. See
12711  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12712  * for a detailed explanation of the infix-to-postfix algorithm on which
12713  * this is based (this code differs in that it applies operators immediately
12714  * to the stack instead of adding them to a queue to end up with an
12715  * expression). */
12716
12717 /* To use the routine, call it with an expression string and error return
12718  * pointer */
12719
12720 /*
12721  * Aug 24, 2001              Manuel Novoa III
12722  *
12723  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12724  *
12725  * 1) In arith_apply():
12726  *    a) Cached values of *numptr and &(numptr[-1]).
12727  *    b) Removed redundant test for zero denominator.
12728  *
12729  * 2) In arith():
12730  *    a) Eliminated redundant code for processing operator tokens by moving
12731  *       to a table-based implementation.  Also folded handling of parens
12732  *       into the table.
12733  *    b) Combined all 3 loops which called arith_apply to reduce generated
12734  *       code size at the cost of speed.
12735  *
12736  * 3) The following expressions were treated as valid by the original code:
12737  *       1()  ,    0!  ,    1 ( *3 )   .
12738  *    These bugs have been fixed by internally enclosing the expression in
12739  *    parens and then checking that all binary ops and right parens are
12740  *    preceded by a valid expression (NUM_TOKEN).
12741  *
12742  * Note: It may be desirable to replace Aaron's test for whitespace with
12743  * ctype's isspace() if it is used by another busybox applet or if additional
12744  * whitespace chars should be considered.  Look below the "#include"s for a
12745  * precompiler test.
12746  */
12747
12748 /*
12749  * Aug 26, 2001              Manuel Novoa III
12750  *
12751  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12752  *
12753  * Merge in Aaron's comments previously posted to the busybox list,
12754  * modified slightly to take account of my changes to the code.
12755  *
12756  */
12757
12758 /*
12759  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12760  *
12761  * - allow access to variable,
12762  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12763  * - realize assign syntax (VAR=expr, +=, *= etc)
12764  * - realize exponentiation (** operator)
12765  * - realize comma separated - expr, expr
12766  * - realise ++expr --expr expr++ expr--
12767  * - realise expr ? expr : expr (but, second expr calculate always)
12768  * - allow hexadecimal and octal numbers
12769  * - was restored loses XOR operator
12770  * - remove one goto label, added three ;-)
12771  * - protect $((num num)) as true zero expr (Manuel`s error)
12772  * - always use special isspace(), see comment from bash ;-)
12773  */
12774
12775 #define arith_isspace(arithval) \
12776         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12777
12778 typedef unsigned char operator;
12779
12780 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12781  * precedence, and 3 high bits are an ID unique across operators of that
12782  * precedence. The ID portion is so that multiple operators can have the
12783  * same precedence, ensuring that the leftmost one is evaluated first.
12784  * Consider * and /. */
12785
12786 #define tok_decl(prec,id) (((id)<<5)|(prec))
12787 #define PREC(op) ((op) & 0x1F)
12788
12789 #define TOK_LPAREN tok_decl(0,0)
12790
12791 #define TOK_COMMA tok_decl(1,0)
12792
12793 #define TOK_ASSIGN tok_decl(2,0)
12794 #define TOK_AND_ASSIGN tok_decl(2,1)
12795 #define TOK_OR_ASSIGN tok_decl(2,2)
12796 #define TOK_XOR_ASSIGN tok_decl(2,3)
12797 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12798 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12799 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12800 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12801
12802 #define TOK_MUL_ASSIGN tok_decl(3,0)
12803 #define TOK_DIV_ASSIGN tok_decl(3,1)
12804 #define TOK_REM_ASSIGN tok_decl(3,2)
12805
12806 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12807 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12808
12809 /* conditional is right associativity too */
12810 #define TOK_CONDITIONAL tok_decl(4,0)
12811 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12812
12813 #define TOK_OR tok_decl(5,0)
12814
12815 #define TOK_AND tok_decl(6,0)
12816
12817 #define TOK_BOR tok_decl(7,0)
12818
12819 #define TOK_BXOR tok_decl(8,0)
12820
12821 #define TOK_BAND tok_decl(9,0)
12822
12823 #define TOK_EQ tok_decl(10,0)
12824 #define TOK_NE tok_decl(10,1)
12825
12826 #define TOK_LT tok_decl(11,0)
12827 #define TOK_GT tok_decl(11,1)
12828 #define TOK_GE tok_decl(11,2)
12829 #define TOK_LE tok_decl(11,3)
12830
12831 #define TOK_LSHIFT tok_decl(12,0)
12832 #define TOK_RSHIFT tok_decl(12,1)
12833
12834 #define TOK_ADD tok_decl(13,0)
12835 #define TOK_SUB tok_decl(13,1)
12836
12837 #define TOK_MUL tok_decl(14,0)
12838 #define TOK_DIV tok_decl(14,1)
12839 #define TOK_REM tok_decl(14,2)
12840
12841 /* exponent is right associativity */
12842 #define TOK_EXPONENT tok_decl(15,1)
12843
12844 /* For now unary operators. */
12845 #define UNARYPREC 16
12846 #define TOK_BNOT tok_decl(UNARYPREC,0)
12847 #define TOK_NOT tok_decl(UNARYPREC,1)
12848
12849 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12850 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12851
12852 #define PREC_PRE (UNARYPREC+2)
12853
12854 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12855 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12856
12857 #define PREC_POST (UNARYPREC+3)
12858
12859 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12860 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12861
12862 #define SPEC_PREC (UNARYPREC+4)
12863
12864 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12865 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12866
12867 #define NUMPTR (*numstackptr)
12868
12869 static int
12870 tok_have_assign(operator op)
12871 {
12872         operator prec = PREC(op);
12873
12874         convert_prec_is_assing(prec);
12875         return (prec == PREC(TOK_ASSIGN) ||
12876                         prec == PREC_PRE || prec == PREC_POST);
12877 }
12878
12879 static int
12880 is_right_associativity(operator prec)
12881 {
12882         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12883                 || prec == PREC(TOK_CONDITIONAL));
12884 }
12885
12886 typedef struct {
12887         arith_t val;
12888         arith_t contidional_second_val;
12889         char contidional_second_val_initialized;
12890         char *var;      /* if NULL then is regular number,
12891                            else is variable name */
12892 } v_n_t;
12893
12894 typedef struct chk_var_recursive_looped_t {
12895         const char *var;
12896         struct chk_var_recursive_looped_t *next;
12897 } chk_var_recursive_looped_t;
12898
12899 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12900
12901 static int
12902 arith_lookup_val(v_n_t *t)
12903 {
12904         if (t->var) {
12905                 const char * p = lookupvar(t->var);
12906
12907                 if (p) {
12908                         int errcode;
12909
12910                         /* recursive try as expression */
12911                         chk_var_recursive_looped_t *cur;
12912                         chk_var_recursive_looped_t cur_save;
12913
12914                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12915                                 if (strcmp(cur->var, t->var) == 0) {
12916                                         /* expression recursion loop detected */
12917                                         return -5;
12918                                 }
12919                         }
12920                         /* save current lookuped var name */
12921                         cur = prev_chk_var_recursive;
12922                         cur_save.var = t->var;
12923                         cur_save.next = cur;
12924                         prev_chk_var_recursive = &cur_save;
12925
12926                         t->val = arith (p, &errcode);
12927                         /* restore previous ptr after recursiving */
12928                         prev_chk_var_recursive = cur;
12929                         return errcode;
12930                 }
12931                 /* allow undefined var as 0 */
12932                 t->val = 0;
12933         }
12934         return 0;
12935 }
12936
12937 /* "applying" a token means performing it on the top elements on the integer
12938  * stack. For a unary operator it will only change the top element, but a
12939  * binary operator will pop two arguments and push a result */
12940 static int
12941 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12942 {
12943         v_n_t *numptr_m1;
12944         arith_t numptr_val, rez;
12945         int ret_arith_lookup_val;
12946
12947         /* There is no operator that can work without arguments */
12948         if (NUMPTR == numstack) goto err;
12949         numptr_m1 = NUMPTR - 1;
12950
12951         /* check operand is var with noninteger value */
12952         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12953         if (ret_arith_lookup_val)
12954                 return ret_arith_lookup_val;
12955
12956         rez = numptr_m1->val;
12957         if (op == TOK_UMINUS)
12958                 rez *= -1;
12959         else if (op == TOK_NOT)
12960                 rez = !rez;
12961         else if (op == TOK_BNOT)
12962                 rez = ~rez;
12963         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12964                 rez++;
12965         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12966                 rez--;
12967         else if (op != TOK_UPLUS) {
12968                 /* Binary operators */
12969
12970                 /* check and binary operators need two arguments */
12971                 if (numptr_m1 == numstack) goto err;
12972
12973                 /* ... and they pop one */
12974                 --NUMPTR;
12975                 numptr_val = rez;
12976                 if (op == TOK_CONDITIONAL) {
12977                         if (!numptr_m1->contidional_second_val_initialized) {
12978                                 /* protect $((expr1 ? expr2)) without ": expr" */
12979                                 goto err;
12980                         }
12981                         rez = numptr_m1->contidional_second_val;
12982                 } else if (numptr_m1->contidional_second_val_initialized) {
12983                         /* protect $((expr1 : expr2)) without "expr ? " */
12984                         goto err;
12985                 }
12986                 numptr_m1 = NUMPTR - 1;
12987                 if (op != TOK_ASSIGN) {
12988                         /* check operand is var with noninteger value for not '=' */
12989                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12990                         if (ret_arith_lookup_val)
12991                                 return ret_arith_lookup_val;
12992                 }
12993                 if (op == TOK_CONDITIONAL) {
12994                         numptr_m1->contidional_second_val = rez;
12995                 }
12996                 rez = numptr_m1->val;
12997                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12998                         rez |= numptr_val;
12999                 else if (op == TOK_OR)
13000                         rez = numptr_val || rez;
13001                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13002                         rez &= numptr_val;
13003                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13004                         rez ^= numptr_val;
13005                 else if (op == TOK_AND)
13006                         rez = rez && numptr_val;
13007                 else if (op == TOK_EQ)
13008                         rez = (rez == numptr_val);
13009                 else if (op == TOK_NE)
13010                         rez = (rez != numptr_val);
13011                 else if (op == TOK_GE)
13012                         rez = (rez >= numptr_val);
13013                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13014                         rez >>= numptr_val;
13015                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13016                         rez <<= numptr_val;
13017                 else if (op == TOK_GT)
13018                         rez = (rez > numptr_val);
13019                 else if (op == TOK_LT)
13020                         rez = (rez < numptr_val);
13021                 else if (op == TOK_LE)
13022                         rez = (rez <= numptr_val);
13023                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13024                         rez *= numptr_val;
13025                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13026                         rez += numptr_val;
13027                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13028                         rez -= numptr_val;
13029                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13030                         rez = numptr_val;
13031                 else if (op == TOK_CONDITIONAL_SEP) {
13032                         if (numptr_m1 == numstack) {
13033                                 /* protect $((expr : expr)) without "expr ? " */
13034                                 goto err;
13035                         }
13036                         numptr_m1->contidional_second_val_initialized = op;
13037                         numptr_m1->contidional_second_val = numptr_val;
13038                 } else if (op == TOK_CONDITIONAL) {
13039                         rez = rez ?
13040                                 numptr_val : numptr_m1->contidional_second_val;
13041                 } else if (op == TOK_EXPONENT) {
13042                         if (numptr_val < 0)
13043                                 return -3;      /* exponent less than 0 */
13044                         else {
13045                                 arith_t c = 1;
13046
13047                                 if (numptr_val)
13048                                         while (numptr_val--)
13049                                                 c *= rez;
13050                                 rez = c;
13051                         }
13052                 } else if (numptr_val==0)          /* zero divisor check */
13053                         return -2;
13054                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13055                         rez /= numptr_val;
13056                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13057                         rez %= numptr_val;
13058         }
13059         if (tok_have_assign(op)) {
13060                 char buf[sizeof(arith_t_type)*3 + 2];
13061
13062                 if (numptr_m1->var == NULL) {
13063                         /* Hmm, 1=2 ? */
13064                         goto err;
13065                 }
13066                 /* save to shell variable */
13067 #if ENABLE_ASH_MATH_SUPPORT_64
13068                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13069 #else
13070                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13071 #endif
13072                 setvar(numptr_m1->var, buf, 0);
13073                 /* after saving, make previous value for v++ or v-- */
13074                 if (op == TOK_POST_INC)
13075                         rez--;
13076                 else if (op == TOK_POST_DEC)
13077                         rez++;
13078         }
13079         numptr_m1->val = rez;
13080         /* protect geting var value, is number now */
13081         numptr_m1->var = NULL;
13082         return 0;
13083  err:
13084         return -1;
13085 }
13086
13087 /* longest must be first */
13088 static const char op_tokens[] ALIGN1 = {
13089         '<','<','=',0, TOK_LSHIFT_ASSIGN,
13090         '>','>','=',0, TOK_RSHIFT_ASSIGN,
13091         '<','<',    0, TOK_LSHIFT,
13092         '>','>',    0, TOK_RSHIFT,
13093         '|','|',    0, TOK_OR,
13094         '&','&',    0, TOK_AND,
13095         '!','=',    0, TOK_NE,
13096         '<','=',    0, TOK_LE,
13097         '>','=',    0, TOK_GE,
13098         '=','=',    0, TOK_EQ,
13099         '|','=',    0, TOK_OR_ASSIGN,
13100         '&','=',    0, TOK_AND_ASSIGN,
13101         '*','=',    0, TOK_MUL_ASSIGN,
13102         '/','=',    0, TOK_DIV_ASSIGN,
13103         '%','=',    0, TOK_REM_ASSIGN,
13104         '+','=',    0, TOK_PLUS_ASSIGN,
13105         '-','=',    0, TOK_MINUS_ASSIGN,
13106         '-','-',    0, TOK_POST_DEC,
13107         '^','=',    0, TOK_XOR_ASSIGN,
13108         '+','+',    0, TOK_POST_INC,
13109         '*','*',    0, TOK_EXPONENT,
13110         '!',        0, TOK_NOT,
13111         '<',        0, TOK_LT,
13112         '>',        0, TOK_GT,
13113         '=',        0, TOK_ASSIGN,
13114         '|',        0, TOK_BOR,
13115         '&',        0, TOK_BAND,
13116         '*',        0, TOK_MUL,
13117         '/',        0, TOK_DIV,
13118         '%',        0, TOK_REM,
13119         '+',        0, TOK_ADD,
13120         '-',        0, TOK_SUB,
13121         '^',        0, TOK_BXOR,
13122         /* uniq */
13123         '~',        0, TOK_BNOT,
13124         ',',        0, TOK_COMMA,
13125         '?',        0, TOK_CONDITIONAL,
13126         ':',        0, TOK_CONDITIONAL_SEP,
13127         ')',        0, TOK_RPAREN,
13128         '(',        0, TOK_LPAREN,
13129         0
13130 };
13131 /* ptr to ")" */
13132 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13133
13134 static arith_t
13135 arith(const char *expr, int *perrcode)
13136 {
13137         char arithval; /* Current character under analysis */
13138         operator lasttok, op;
13139         operator prec;
13140         operator *stack, *stackptr;
13141         const char *p = endexpression;
13142         int errcode;
13143         v_n_t *numstack, *numstackptr;
13144         unsigned datasizes = strlen(expr) + 2;
13145
13146         /* Stack of integers */
13147         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13148          * in any given correct or incorrect expression is left as an exercise to
13149          * the reader. */
13150         numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13151         /* Stack of operator tokens */
13152         stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13153
13154         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
13155         *perrcode = errcode = 0;
13156
13157         while (1) {
13158                 arithval = *expr;
13159                 if (arithval == 0) {
13160                         if (p == endexpression) {
13161                                 /* Null expression. */
13162                                 return 0;
13163                         }
13164
13165                         /* This is only reached after all tokens have been extracted from the
13166                          * input stream. If there are still tokens on the operator stack, they
13167                          * are to be applied in order. At the end, there should be a final
13168                          * result on the integer stack */
13169
13170                         if (expr != endexpression + 1) {
13171                                 /* If we haven't done so already, */
13172                                 /* append a closing right paren */
13173                                 expr = endexpression;
13174                                 /* and let the loop process it. */
13175                                 continue;
13176                         }
13177                         /* At this point, we're done with the expression. */
13178                         if (numstackptr != numstack+1) {
13179                                 /* ... but if there isn't, it's bad */
13180  err:
13181                                 *perrcode = -1;
13182                                 return *perrcode;
13183                         }
13184                         if (numstack->var) {
13185                                 /* expression is $((var)) only, lookup now */
13186                                 errcode = arith_lookup_val(numstack);
13187                         }
13188  ret:
13189                         *perrcode = errcode;
13190                         return numstack->val;
13191                 }
13192
13193                 /* Continue processing the expression. */
13194                 if (arith_isspace(arithval)) {
13195                         /* Skip whitespace */
13196                         goto prologue;
13197                 }
13198                 p = endofname(expr);
13199                 if (p != expr) {
13200                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
13201
13202                         numstackptr->var = alloca(var_name_size);
13203                         safe_strncpy(numstackptr->var, expr, var_name_size);
13204                         expr = p;
13205  num:
13206                         numstackptr->contidional_second_val_initialized = 0;
13207                         numstackptr++;
13208                         lasttok = TOK_NUM;
13209                         continue;
13210                 }
13211                 if (isdigit(arithval)) {
13212                         numstackptr->var = NULL;
13213 #if ENABLE_ASH_MATH_SUPPORT_64
13214                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
13215 #else
13216                         numstackptr->val = strtol(expr, (char **) &expr, 0);
13217 #endif
13218                         goto num;
13219                 }
13220                 for (p = op_tokens; ; p++) {
13221                         const char *o;
13222
13223                         if (*p == 0) {
13224                                 /* strange operator not found */
13225                                 goto err;
13226                         }
13227                         for (o = expr; *p && *o == *p; p++)
13228                                 o++;
13229                         if (!*p) {
13230                                 /* found */
13231                                 expr = o - 1;
13232                                 break;
13233                         }
13234                         /* skip tail uncompared token */
13235                         while (*p)
13236                                 p++;
13237                         /* skip zero delim */
13238                         p++;
13239                 }
13240                 op = p[1];
13241
13242                 /* post grammar: a++ reduce to num */
13243                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13244                         lasttok = TOK_NUM;
13245
13246                 /* Plus and minus are binary (not unary) _only_ if the last
13247                  * token was as number, or a right paren (which pretends to be
13248                  * a number, since it evaluates to one). Think about it.
13249                  * It makes sense. */
13250                 if (lasttok != TOK_NUM) {
13251                         switch (op) {
13252                         case TOK_ADD:
13253                                 op = TOK_UPLUS;
13254                                 break;
13255                         case TOK_SUB:
13256                                 op = TOK_UMINUS;
13257                                 break;
13258                         case TOK_POST_INC:
13259                                 op = TOK_PRE_INC;
13260                                 break;
13261                         case TOK_POST_DEC:
13262                                 op = TOK_PRE_DEC;
13263                                 break;
13264                         }
13265                 }
13266                 /* We don't want a unary operator to cause recursive descent on the
13267                  * stack, because there can be many in a row and it could cause an
13268                  * operator to be evaluated before its argument is pushed onto the
13269                  * integer stack. */
13270                 /* But for binary operators, "apply" everything on the operator
13271                  * stack until we find an operator with a lesser priority than the
13272                  * one we have just extracted. */
13273                 /* Left paren is given the lowest priority so it will never be
13274                  * "applied" in this way.
13275                  * if associativity is right and priority eq, applied also skip
13276                  */
13277                 prec = PREC(op);
13278                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13279                         /* not left paren or unary */
13280                         if (lasttok != TOK_NUM) {
13281                                 /* binary op must be preceded by a num */
13282                                 goto err;
13283                         }
13284                         while (stackptr != stack) {
13285                                 if (op == TOK_RPAREN) {
13286                                         /* The algorithm employed here is simple: while we don't
13287                                          * hit an open paren nor the bottom of the stack, pop
13288                                          * tokens and apply them */
13289                                         if (stackptr[-1] == TOK_LPAREN) {
13290                                                 --stackptr;
13291                                                 /* Any operator directly after a */
13292                                                 lasttok = TOK_NUM;
13293                                                 /* close paren should consider itself binary */
13294                                                 goto prologue;
13295                                         }
13296                                 } else {
13297                                         operator prev_prec = PREC(stackptr[-1]);
13298
13299                                         convert_prec_is_assing(prec);
13300                                         convert_prec_is_assing(prev_prec);
13301                                         if (prev_prec < prec)
13302                                                 break;
13303                                         /* check right assoc */
13304                                         if (prev_prec == prec && is_right_associativity(prec))
13305                                                 break;
13306                                 }
13307                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13308                                 if (errcode) goto ret;
13309                         }
13310                         if (op == TOK_RPAREN) {
13311                                 goto err;
13312                         }
13313                 }
13314
13315                 /* Push this operator to the stack and remember it. */
13316                 *stackptr++ = lasttok = op;
13317  prologue:
13318                 ++expr;
13319         } /* while */
13320 }
13321 #endif /* ASH_MATH_SUPPORT */
13322
13323
13324 /* ============ main() and helpers */
13325
13326 /*
13327  * Called to exit the shell.
13328  */
13329 static void exitshell(void) NORETURN;
13330 static void
13331 exitshell(void)
13332 {
13333         struct jmploc loc;
13334         char *p;
13335         int status;
13336
13337         status = exitstatus;
13338         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13339         if (setjmp(loc.loc)) {
13340                 if (exception == EXEXIT)
13341 /* dash bug: it just does _exit(exitstatus) here
13342  * but we have to do setjobctl(0) first!
13343  * (bug is still not fixed in dash-0.5.3 - if you run dash
13344  * under Midnight Commander, on exit from dash MC is backgrounded) */
13345                         status = exitstatus;
13346                 goto out;
13347         }
13348         exception_handler = &loc;
13349         p = trap[0];
13350         if (p) {
13351                 trap[0] = NULL;
13352                 evalstring(p, 0);
13353         }
13354         flush_stdout_stderr();
13355  out:
13356         setjobctl(0);
13357         _exit(status);
13358         /* NOTREACHED */
13359 }
13360
13361 static void
13362 init(void)
13363 {
13364         /* from input.c: */
13365         basepf.nextc = basepf.buf = basebuf;
13366
13367         /* from trap.c: */
13368         signal(SIGCHLD, SIG_DFL);
13369
13370         /* from var.c: */
13371         {
13372                 char **envp;
13373                 char ppid[sizeof(int)*3 + 1];
13374                 const char *p;
13375                 struct stat st1, st2;
13376
13377                 initvar();
13378                 for (envp = environ; envp && *envp; envp++) {
13379                         if (strchr(*envp, '=')) {
13380                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13381                         }
13382                 }
13383
13384                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13385                 setvar("PPID", ppid, 0);
13386
13387                 p = lookupvar("PWD");
13388                 if (p)
13389                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13390                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13391                                 p = '\0';
13392                 setpwd(p, 0);
13393         }
13394 }
13395
13396 /*
13397  * Process the shell command line arguments.
13398  */
13399 static void
13400 procargs(char **argv)
13401 {
13402         int i;
13403         const char *xminusc;
13404         char **xargv;
13405
13406         xargv = argv;
13407         arg0 = xargv[0];
13408         /* if (xargv[0]) - mmm, this is always true! */
13409                 xargv++;
13410         for (i = 0; i < NOPTS; i++)
13411                 optlist[i] = 2;
13412         argptr = xargv;
13413         if (options(1)) {
13414                 /* it already printed err message */
13415                 raise_exception(EXERROR);
13416         }
13417         xargv = argptr;
13418         xminusc = minusc;
13419         if (*xargv == NULL) {
13420                 if (xminusc)
13421                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13422                 sflag = 1;
13423         }
13424         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13425                 iflag = 1;
13426         if (mflag == 2)
13427                 mflag = iflag;
13428         for (i = 0; i < NOPTS; i++)
13429                 if (optlist[i] == 2)
13430                         optlist[i] = 0;
13431 #if DEBUG == 2
13432         debug = 1;
13433 #endif
13434         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13435         if (xminusc) {
13436                 minusc = *xargv++;
13437                 if (*xargv)
13438                         goto setarg0;
13439         } else if (!sflag) {
13440                 setinputfile(*xargv, 0);
13441  setarg0:
13442                 arg0 = *xargv++;
13443                 commandname = arg0;
13444         }
13445
13446         shellparam.p = xargv;
13447 #if ENABLE_ASH_GETOPTS
13448         shellparam.optind = 1;
13449         shellparam.optoff = -1;
13450 #endif
13451         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13452         while (*xargv) {
13453                 shellparam.nparam++;
13454                 xargv++;
13455         }
13456         optschanged();
13457 }
13458
13459 /*
13460  * Read /etc/profile or .profile.
13461  */
13462 static void
13463 read_profile(const char *name)
13464 {
13465         int skip;
13466
13467         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13468                 return;
13469         skip = cmdloop(0);
13470         popfile();
13471         if (skip)
13472                 exitshell();
13473 }
13474
13475 /*
13476  * This routine is called when an error or an interrupt occurs in an
13477  * interactive shell and control is returned to the main command loop.
13478  */
13479 static void
13480 reset(void)
13481 {
13482         /* from eval.c: */
13483         evalskip = 0;
13484         loopnest = 0;
13485         /* from input.c: */
13486         parselleft = parsenleft = 0;      /* clear input buffer */
13487         popallfiles();
13488         /* from parser.c: */
13489         tokpushback = 0;
13490         checkkwd = 0;
13491         /* from redir.c: */
13492         clearredir(/*drop:*/ 0);
13493 }
13494
13495 #if PROFILE
13496 static short profile_buf[16384];
13497 extern int etext();
13498 #endif
13499
13500 /*
13501  * Main routine.  We initialize things, parse the arguments, execute
13502  * profiles if we're a login shell, and then call cmdloop to execute
13503  * commands.  The setjmp call sets up the location to jump to when an
13504  * exception occurs.  When an exception occurs the variable "state"
13505  * is used to figure out how far we had gotten.
13506  */
13507 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13508 int ash_main(int argc UNUSED_PARAM, char **argv)
13509 {
13510         char *shinit;
13511         volatile int state;
13512         struct jmploc jmploc;
13513         struct stackmark smark;
13514
13515         /* Initialize global data */
13516         INIT_G_misc();
13517         INIT_G_memstack();
13518         INIT_G_var();
13519 #if ENABLE_ASH_ALIAS
13520         INIT_G_alias();
13521 #endif
13522         INIT_G_cmdtable();
13523
13524 #if PROFILE
13525         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13526 #endif
13527
13528 #if ENABLE_FEATURE_EDITING
13529         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13530 #endif
13531         state = 0;
13532         if (setjmp(jmploc.loc)) {
13533                 int e;
13534                 int s;
13535
13536                 reset();
13537
13538                 e = exception;
13539                 if (e == EXERROR)
13540                         exitstatus = 2;
13541                 s = state;
13542                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13543                         exitshell();
13544
13545                 if (e == EXINT) {
13546                         outcslow('\n', stderr);
13547                 }
13548                 popstackmark(&smark);
13549                 FORCE_INT_ON; /* enable interrupts */
13550                 if (s == 1)
13551                         goto state1;
13552                 if (s == 2)
13553                         goto state2;
13554                 if (s == 3)
13555                         goto state3;
13556                 goto state4;
13557         }
13558         exception_handler = &jmploc;
13559 #if DEBUG
13560         opentrace();
13561         trace_puts("Shell args: ");
13562         trace_puts_args(argv);
13563 #endif
13564         rootpid = getpid();
13565
13566 #if ENABLE_ASH_RANDOM_SUPPORT
13567         /* Can use monotonic_ns() for better randomness but for now it is
13568          * not used anywhere else in busybox... so avoid bloat */
13569         random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13570 #endif
13571         init();
13572         setstackmark(&smark);
13573         procargs(argv);
13574
13575 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13576         if (iflag) {
13577                 const char *hp = lookupvar("HISTFILE");
13578
13579                 if (hp == NULL) {
13580                         hp = lookupvar("HOME");
13581                         if (hp != NULL) {
13582                                 char *defhp = concat_path_file(hp, ".ash_history");
13583                                 setvar("HISTFILE", defhp, 0);
13584                                 free(defhp);
13585                         }
13586                 }
13587         }
13588 #endif
13589         if (argv[0] && argv[0][0] == '-')
13590                 isloginsh = 1;
13591         if (isloginsh) {
13592                 state = 1;
13593                 read_profile("/etc/profile");
13594  state1:
13595                 state = 2;
13596                 read_profile(".profile");
13597         }
13598  state2:
13599         state = 3;
13600         if (
13601 #ifndef linux
13602          getuid() == geteuid() && getgid() == getegid() &&
13603 #endif
13604          iflag
13605         ) {
13606                 shinit = lookupvar("ENV");
13607                 if (shinit != NULL && *shinit != '\0') {
13608                         read_profile(shinit);
13609                 }
13610         }
13611  state3:
13612         state = 4;
13613         if (minusc)
13614                 evalstring(minusc, 0);
13615
13616         if (sflag || minusc == NULL) {
13617 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13618                 if (iflag) {
13619                         const char *hp = lookupvar("HISTFILE");
13620
13621                         if (hp != NULL)
13622                                 line_input_state->hist_file = hp;
13623                 }
13624 #endif
13625  state4: /* XXX ??? - why isn't this before the "if" statement */
13626                 cmdloop(1);
13627         }
13628 #if PROFILE
13629         monitor(0);
13630 #endif
13631 #ifdef GPROF
13632         {
13633                 extern void _mcleanup(void);
13634                 _mcleanup();
13635         }
13636 #endif
13637         exitshell();
13638         /* NOTREACHED */
13639 }
13640
13641 #if DEBUG
13642 const char *applet_name = "debug stuff usage";
13643 int main(int argc, char **argv)
13644 {
13645         return ash_main(argc, argv);
13646 }
13647 #endif
13648
13649
13650 /*-
13651  * Copyright (c) 1989, 1991, 1993, 1994
13652  *      The Regents of the University of California.  All rights reserved.
13653  *
13654  * This code is derived from software contributed to Berkeley by
13655  * Kenneth Almquist.
13656  *
13657  * Redistribution and use in source and binary forms, with or without
13658  * modification, are permitted provided that the following conditions
13659  * are met:
13660  * 1. Redistributions of source code must retain the above copyright
13661  *    notice, this list of conditions and the following disclaimer.
13662  * 2. Redistributions in binary form must reproduce the above copyright
13663  *    notice, this list of conditions and the following disclaimer in the
13664  *    documentation and/or other materials provided with the distribution.
13665  * 3. Neither the name of the University nor the names of its contributors
13666  *    may be used to endorse or promote products derived from this software
13667  *    without specific prior written permission.
13668  *
13669  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13670  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13671  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13672  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13673  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13674  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13675  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13676  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13677  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13678  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13679  * SUCH DAMAGE.
13680  */