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