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