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