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