debe8ecddf2fced9862158670b38ae59a1f79fa4
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9  * was re-ported from NetBSD and debianized.
10  *
11  *
12  * This code is derived from software contributed to Berkeley by
13  * Kenneth Almquist.
14  *
15  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
16  *
17  * Original BSD copyright notice is retained at the end of this file.
18  */
19
20 /*
21  * rewrite arith.y to micro stack based cryptic algorithm by
22  * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
23  *
24  * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
25  * dynamic variables.
26  *
27  * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28  * used in busybox and size optimizations,
29  * rewrote arith (see notes to this), added locale support,
30  * rewrote dynamic variables.
31  *
32  */
33
34 /*
35  * The follow should be set to reflect the type of system you have:
36  *      JOBS -> 1 if you have Berkeley job control, 0 otherwise.
37  *      define SYSV if you are running under System V.
38  *      define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
39  *      define DEBUG=2 to compile in and turn on debugging.
40  *
41  * When debugging is on, debugging info will be written to ./trace and
42  * a quit signal will generate a core dump.
43  */
44 #define DEBUG 0
45 #define PROFILE 0
46
47 #define IFS_BROKEN
48
49 #define JOBS ENABLE_ASH_JOB_CONTROL
50
51 #if DEBUG
52 #ifndef _GNU_SOURCE
53 #define _GNU_SOURCE
54 #endif
55 #endif
56
57 #include "busybox.h" /* for applet_names */
58 #include <paths.h>
59 #include <setjmp.h>
60 #include <fnmatch.h>
61 #if JOBS || ENABLE_ASH_READ_NCHARS
62 #include <termios.h>
63 #endif
64
65 #if defined(__uClinux__)
66 #error "Do not even bother, ash will not run on uClinux"
67 #endif
68
69
70 /* ============ Hash table sizes. Configurable. */
71
72 #define VTABSIZE 39
73 #define ATABSIZE 39
74 #define CMDTABLESIZE 31         /* should be prime */
75
76
77 /* ============ Misc helpers */
78
79 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
80
81 /* C99 say: "char" declaration may be signed or unsigned default */
82 #define signed_char2int(sc) ((int)((signed char)sc))
83
84
85 /* ============ Shell options */
86
87 static const char *const optletters_optnames[] = {
88         "e"   "errexit",
89         "f"   "noglob",
90         "I"   "ignoreeof",
91         "i"   "interactive",
92         "m"   "monitor",
93         "n"   "noexec",
94         "s"   "stdin",
95         "x"   "xtrace",
96         "v"   "verbose",
97         "C"   "noclobber",
98         "a"   "allexport",
99         "b"   "notify",
100         "u"   "nounset",
101         "\0"  "vi"
102 #if DEBUG
103         ,"\0"  "nolog"
104         ,"\0"  "debug"
105 #endif
106 };
107
108 #define optletters(n) optletters_optnames[(n)][0]
109 #define optnames(n) (&optletters_optnames[(n)][1])
110
111 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
112
113 static char optlist[NOPTS] ALIGN1;
114
115 #define eflag optlist[0]
116 #define fflag optlist[1]
117 #define Iflag optlist[2]
118 #define iflag optlist[3]
119 #define mflag optlist[4]
120 #define nflag optlist[5]
121 #define sflag optlist[6]
122 #define xflag optlist[7]
123 #define vflag optlist[8]
124 #define Cflag optlist[9]
125 #define aflag optlist[10]
126 #define bflag optlist[11]
127 #define uflag optlist[12]
128 #define viflag optlist[13]
129 #if DEBUG
130 #define nolog optlist[14]
131 #define debug optlist[15]
132 #endif
133
134
135 /* ============ Misc data */
136
137 static const char homestr[] ALIGN1 = "HOME";
138 static const char snlfmt[] ALIGN1 = "%s\n";
139 static const char illnum[] ALIGN1 = "Illegal number: %s";
140
141 /*
142  * We enclose jmp_buf in a structure so that we can declare pointers to
143  * jump locations.  The global variable handler contains the location to
144  * jump to when an exception occurs, and the global variable exception
145  * contains a code identifying the exception.  To implement nested
146  * exception handlers, the user should save the value of handler on entry
147  * to an inner scope, set handler to point to a jmploc structure for the
148  * inner scope, and restore handler on exit from the scope.
149  */
150 struct jmploc {
151         jmp_buf loc;
152 };
153
154 struct globals_misc {
155         /* pid of main shell */
156         int rootpid;
157         /* shell level: 0 for the main shell, 1 for its children, and so on */
158         int shlvl;
159 #define rootshell (!shlvl)
160         char *minusc;  /* argument to -c option */
161
162         char *curdir; // = nullstr;     /* current working directory */
163         char *physdir; // = nullstr;    /* physical working directory */
164
165         char *arg0; /* value of $0 */
166
167         struct jmploc *exception_handler;
168
169 // disabled by vda: cannot understand how it was supposed to work -
170 // cannot fix bugs. That's why you have to explain your non-trivial designs!
171 //      /* do we generate EXSIG events */
172 //      int exsig; /* counter */
173         volatile int suppressint; /* counter */
174         volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
175         /* last pending signal */
176         volatile /*sig_atomic_t*/ smallint pendingsig;
177         smallint exception; /* kind of exception (0..5) */
178         /* exceptions */
179 #define EXINT 0         /* SIGINT received */
180 #define EXERROR 1       /* a generic error */
181 #define EXSHELLPROC 2   /* execute a shell procedure */
182 #define EXEXEC 3        /* command execution failed */
183 #define EXEXIT 4        /* exit the shell */
184 #define EXSIG 5         /* trapped signal in wait(1) */
185
186         /* trap handler commands */
187         char *trap[NSIG];
188         smallint isloginsh;
189         char nullstr[1];                /* zero length string */
190         /*
191          * Sigmode records the current value of the signal handlers for the various
192          * modes.  A value of zero means that the current handler is not known.
193          * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
194          */
195         char sigmode[NSIG - 1];
196 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
197 #define S_CATCH 2               /* signal is caught */
198 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
199 #define S_HARD_IGN 4            /* signal is ignored permenantly */
200 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
201
202         /* indicates specified signal received */
203         char gotsig[NSIG - 1];
204 };
205 /* 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 = ckmalloc(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 = ckmalloc(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 = stalloc(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 = stalloc(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 = stalloc(sizeof(struct nodelist));
9652                 pipenode->npipe.cmdlist = lp;
9653                 lp->n = n1;
9654                 do {
9655                         prev = lp;
9656                         lp = stalloc(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 = stalloc(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                         p->next = here;
9752                 }
9753         } else if (n->type == NTOFD || n->type == NFROMFD) {
9754                 fixredir(n, wordtext, 0);
9755         } else {
9756                 n->nfile.fname = makename();
9757         }
9758 }
9759
9760 static union node *
9761 simplecmd(void)
9762 {
9763         union node *args, **app;
9764         union node *n = NULL;
9765         union node *vars, **vpp;
9766         union node **rpp, *redir;
9767         int savecheckkwd;
9768
9769         args = NULL;
9770         app = &args;
9771         vars = NULL;
9772         vpp = &vars;
9773         redir = NULL;
9774         rpp = &redir;
9775
9776         savecheckkwd = CHKALIAS;
9777         for (;;) {
9778                 checkkwd = savecheckkwd;
9779                 switch (readtoken()) {
9780                 case TWORD:
9781                         n = stzalloc(sizeof(struct narg));
9782                         n->type = NARG;
9783                         /*n->narg.next = NULL; - stzalloc did it */
9784                         n->narg.text = wordtext;
9785                         n->narg.backquote = backquotelist;
9786                         if (savecheckkwd && isassignment(wordtext)) {
9787                                 *vpp = n;
9788                                 vpp = &n->narg.next;
9789                         } else {
9790                                 *app = n;
9791                                 app = &n->narg.next;
9792                                 savecheckkwd = 0;
9793                         }
9794                         break;
9795                 case TREDIR:
9796                         *rpp = n = redirnode;
9797                         rpp = &n->nfile.next;
9798                         parsefname();   /* read name of redirection file */
9799                         break;
9800                 case TLP:
9801                         if (args && app == &args->narg.next
9802                          && !vars && !redir
9803                         ) {
9804                                 struct builtincmd *bcmd;
9805                                 const char *name;
9806
9807                                 /* We have a function */
9808                                 if (readtoken() != TRP)
9809                                         raise_error_unexpected_syntax(TRP);
9810                                 name = n->narg.text;
9811                                 if (!goodname(name)
9812                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9813                                 ) {
9814                                         raise_error_syntax("Bad function name");
9815                                 }
9816                                 n->type = NDEFUN;
9817                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9818                                 n->narg.next = parse_command();
9819                                 return n;
9820                         }
9821                         /* fall through */
9822                 default:
9823                         tokpushback = 1;
9824                         goto out;
9825                 }
9826         }
9827  out:
9828         *app = NULL;
9829         *vpp = NULL;
9830         *rpp = NULL;
9831         n = stalloc(sizeof(struct ncmd));
9832         n->type = NCMD;
9833         n->ncmd.args = args;
9834         n->ncmd.assign = vars;
9835         n->ncmd.redirect = redir;
9836         return n;
9837 }
9838
9839 static union node *
9840 parse_command(void)
9841 {
9842         union node *n1, *n2;
9843         union node *ap, **app;
9844         union node *cp, **cpp;
9845         union node *redir, **rpp;
9846         union node **rpp2;
9847         int t;
9848
9849         redir = NULL;
9850         rpp2 = &redir;
9851
9852         switch (readtoken()) {
9853         default:
9854                 raise_error_unexpected_syntax(-1);
9855                 /* NOTREACHED */
9856         case TIF:
9857                 n1 = stalloc(sizeof(struct nif));
9858                 n1->type = NIF;
9859                 n1->nif.test = list(0);
9860                 if (readtoken() != TTHEN)
9861                         raise_error_unexpected_syntax(TTHEN);
9862                 n1->nif.ifpart = list(0);
9863                 n2 = n1;
9864                 while (readtoken() == TELIF) {
9865                         n2->nif.elsepart = stalloc(sizeof(struct nif));
9866                         n2 = n2->nif.elsepart;
9867                         n2->type = NIF;
9868                         n2->nif.test = list(0);
9869                         if (readtoken() != TTHEN)
9870                                 raise_error_unexpected_syntax(TTHEN);
9871                         n2->nif.ifpart = list(0);
9872                 }
9873                 if (lasttoken == TELSE)
9874                         n2->nif.elsepart = list(0);
9875                 else {
9876                         n2->nif.elsepart = NULL;
9877                         tokpushback = 1;
9878                 }
9879                 t = TFI;
9880                 break;
9881         case TWHILE:
9882         case TUNTIL: {
9883                 int got;
9884                 n1 = stalloc(sizeof(struct nbinary));
9885                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9886                 n1->nbinary.ch1 = list(0);
9887                 got = readtoken();
9888                 if (got != TDO) {
9889                         TRACE(("expecting DO got %s %s\n", tokname(got),
9890                                         got == TWORD ? wordtext : ""));
9891                         raise_error_unexpected_syntax(TDO);
9892                 }
9893                 n1->nbinary.ch2 = list(0);
9894                 t = TDONE;
9895                 break;
9896         }
9897         case TFOR:
9898                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9899                         raise_error_syntax("Bad for loop variable");
9900                 n1 = stalloc(sizeof(struct nfor));
9901                 n1->type = NFOR;
9902                 n1->nfor.var = wordtext;
9903                 checkkwd = CHKKWD | CHKALIAS;
9904                 if (readtoken() == TIN) {
9905                         app = &ap;
9906                         while (readtoken() == TWORD) {
9907                                 n2 = stzalloc(sizeof(struct narg));
9908                                 n2->type = NARG;
9909                                 /*n2->narg.next = NULL; - stzalloc did it */
9910                                 n2->narg.text = wordtext;
9911                                 n2->narg.backquote = backquotelist;
9912                                 *app = n2;
9913                                 app = &n2->narg.next;
9914                         }
9915                         *app = NULL;
9916                         n1->nfor.args = ap;
9917                         if (lasttoken != TNL && lasttoken != TSEMI)
9918                                 raise_error_unexpected_syntax(-1);
9919                 } else {
9920                         n2 = stzalloc(sizeof(struct narg));
9921                         n2->type = NARG;
9922                         /*n2->narg.next = NULL; - stzalloc did it */
9923                         n2->narg.text = (char *)dolatstr;
9924                         /*n2->narg.backquote = NULL;*/
9925                         n1->nfor.args = n2;
9926                         /*
9927                          * Newline or semicolon here is optional (but note
9928                          * that the original Bourne shell only allowed NL).
9929                          */
9930                         if (lasttoken != TNL && lasttoken != TSEMI)
9931                                 tokpushback = 1;
9932                 }
9933                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9934                 if (readtoken() != TDO)
9935                         raise_error_unexpected_syntax(TDO);
9936                 n1->nfor.body = list(0);
9937                 t = TDONE;
9938                 break;
9939         case TCASE:
9940                 n1 = stalloc(sizeof(struct ncase));
9941                 n1->type = NCASE;
9942                 if (readtoken() != TWORD)
9943                         raise_error_unexpected_syntax(TWORD);
9944                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
9945                 n2->type = NARG;
9946                 /*n2->narg.next = NULL; - stzalloc did it */
9947                 n2->narg.text = wordtext;
9948                 n2->narg.backquote = backquotelist;
9949                 do {
9950                         checkkwd = CHKKWD | CHKALIAS;
9951                 } while (readtoken() == TNL);
9952                 if (lasttoken != TIN)
9953                         raise_error_unexpected_syntax(TIN);
9954                 cpp = &n1->ncase.cases;
9955  next_case:
9956                 checkkwd = CHKNL | CHKKWD;
9957                 t = readtoken();
9958                 while (t != TESAC) {
9959                         if (lasttoken == TLP)
9960                                 readtoken();
9961                         *cpp = cp = stalloc(sizeof(struct nclist));
9962                         cp->type = NCLIST;
9963                         app = &cp->nclist.pattern;
9964                         for (;;) {
9965                                 *app = ap = stzalloc(sizeof(struct narg));
9966                                 ap->type = NARG;
9967                                 /*ap->narg.next = NULL; - stzalloc did it */
9968                                 ap->narg.text = wordtext;
9969                                 ap->narg.backquote = backquotelist;
9970                                 if (readtoken() != TPIPE)
9971                                         break;
9972                                 app = &ap->narg.next;
9973                                 readtoken();
9974                         }
9975                         //ap->narg.next = NULL;
9976                         if (lasttoken != TRP)
9977                                 raise_error_unexpected_syntax(TRP);
9978                         cp->nclist.body = list(2);
9979
9980                         cpp = &cp->nclist.next;
9981
9982                         checkkwd = CHKNL | CHKKWD;
9983                         t = readtoken();
9984                         if (t != TESAC) {
9985                                 if (t != TENDCASE)
9986                                         raise_error_unexpected_syntax(TENDCASE);
9987                                 goto next_case;
9988                         }
9989                 }
9990                 *cpp = NULL;
9991                 goto redir;
9992         case TLP:
9993                 n1 = stzalloc(sizeof(struct nredir));
9994                 n1->type = NSUBSHELL;
9995                 n1->nredir.n = list(0);
9996                 /*n1->nredir.redirect = NULL; - stzalloc did it */
9997                 t = TRP;
9998                 break;
9999         case TBEGIN:
10000                 n1 = list(0);
10001                 t = TEND;
10002                 break;
10003         case TWORD:
10004         case TREDIR:
10005                 tokpushback = 1;
10006                 return simplecmd();
10007         }
10008
10009         if (readtoken() != t)
10010                 raise_error_unexpected_syntax(t);
10011
10012  redir:
10013         /* Now check for redirection which may follow command */
10014         checkkwd = CHKKWD | CHKALIAS;
10015         rpp = rpp2;
10016         while (readtoken() == TREDIR) {
10017                 *rpp = n2 = redirnode;
10018                 rpp = &n2->nfile.next;
10019                 parsefname();
10020         }
10021         tokpushback = 1;
10022         *rpp = NULL;
10023         if (redir) {
10024                 if (n1->type != NSUBSHELL) {
10025                         n2 = stzalloc(sizeof(struct nredir));
10026                         n2->type = NREDIR;
10027                         n2->nredir.n = n1;
10028                         n1 = n2;
10029                 }
10030                 n1->nredir.redirect = redir;
10031         }
10032         return n1;
10033 }
10034
10035 /*
10036  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10037  * is not NULL, read a here document.  In the latter case, eofmark is the
10038  * word which marks the end of the document and striptabs is true if
10039  * leading tabs should be stripped from the document.  The argument firstc
10040  * is the first character of the input token or document.
10041  *
10042  * Because C does not have internal subroutines, I have simulated them
10043  * using goto's to implement the subroutine linkage.  The following macros
10044  * will run code that appears at the end of readtoken1.
10045  */
10046
10047 #define CHECKEND()      {goto checkend; checkend_return:;}
10048 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10049 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10050 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10051 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10052 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10053
10054 static int
10055 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10056 {
10057         /* NB: syntax parameter fits into smallint */
10058         int c = firstc;
10059         char *out;
10060         int len;
10061         char line[EOFMARKLEN + 1];
10062         struct nodelist *bqlist;
10063         smallint quotef;
10064         smallint dblquote;
10065         smallint oldstyle;
10066         smallint prevsyntax; /* syntax before arithmetic */
10067 #if ENABLE_ASH_EXPAND_PRMT
10068         smallint pssyntax;   /* we are expanding a prompt string */
10069 #endif
10070         int varnest;         /* levels of variables expansion */
10071         int arinest;         /* levels of arithmetic expansion */
10072         int parenlevel;      /* levels of parens in arithmetic */
10073         int dqvarnest;       /* levels of variables expansion within double quotes */
10074
10075 #if __GNUC__
10076         /* Avoid longjmp clobbering */
10077         (void) &out;
10078         (void) &quotef;
10079         (void) &dblquote;
10080         (void) &varnest;
10081         (void) &arinest;
10082         (void) &parenlevel;
10083         (void) &dqvarnest;
10084         (void) &oldstyle;
10085         (void) &prevsyntax;
10086         (void) &syntax;
10087 #endif
10088         startlinno = plinno;
10089         bqlist = NULL;
10090         quotef = 0;
10091         oldstyle = 0;
10092         prevsyntax = 0;
10093 #if ENABLE_ASH_EXPAND_PRMT
10094         pssyntax = (syntax == PSSYNTAX);
10095         if (pssyntax)
10096                 syntax = DQSYNTAX;
10097 #endif
10098         dblquote = (syntax == DQSYNTAX);
10099         varnest = 0;
10100         arinest = 0;
10101         parenlevel = 0;
10102         dqvarnest = 0;
10103
10104         STARTSTACKSTR(out);
10105         loop: { /* for each line, until end of word */
10106                 CHECKEND();     /* set c to PEOF if at end of here document */
10107                 for (;;) {      /* until end of line or end of word */
10108                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10109                         switch (SIT(c, syntax)) {
10110                         case CNL:       /* '\n' */
10111                                 if (syntax == BASESYNTAX)
10112                                         goto endword;   /* exit outer loop */
10113                                 USTPUTC(c, out);
10114                                 plinno++;
10115                                 if (doprompt)
10116                                         setprompt(2);
10117                                 c = pgetc();
10118                                 goto loop;              /* continue outer loop */
10119                         case CWORD:
10120                                 USTPUTC(c, out);
10121                                 break;
10122                         case CCTL:
10123                                 if (eofmark == NULL || dblquote)
10124                                         USTPUTC(CTLESC, out);
10125                                 USTPUTC(c, out);
10126                                 break;
10127                         case CBACK:     /* backslash */
10128                                 c = pgetc2();
10129                                 if (c == PEOF) {
10130                                         USTPUTC(CTLESC, out);
10131                                         USTPUTC('\\', out);
10132                                         pungetc();
10133                                 } else if (c == '\n') {
10134                                         if (doprompt)
10135                                                 setprompt(2);
10136                                 } else {
10137 #if ENABLE_ASH_EXPAND_PRMT
10138                                         if (c == '$' && pssyntax) {
10139                                                 USTPUTC(CTLESC, out);
10140                                                 USTPUTC('\\', out);
10141                                         }
10142 #endif
10143                                         if (dblquote &&
10144                                                 c != '\\' && c != '`' &&
10145                                                 c != '$' && (
10146                                                         c != '"' ||
10147                                                         eofmark != NULL)
10148                                         ) {
10149                                                 USTPUTC(CTLESC, out);
10150                                                 USTPUTC('\\', out);
10151                                         }
10152                                         if (SIT(c, SQSYNTAX) == CCTL)
10153                                                 USTPUTC(CTLESC, out);
10154                                         USTPUTC(c, out);
10155                                         quotef = 1;
10156                                 }
10157                                 break;
10158                         case CSQUOTE:
10159                                 syntax = SQSYNTAX;
10160  quotemark:
10161                                 if (eofmark == NULL) {
10162                                         USTPUTC(CTLQUOTEMARK, out);
10163                                 }
10164                                 break;
10165                         case CDQUOTE:
10166                                 syntax = DQSYNTAX;
10167                                 dblquote = 1;
10168                                 goto quotemark;
10169                         case CENDQUOTE:
10170                                 if (eofmark != NULL && arinest == 0
10171                                  && varnest == 0
10172                                 ) {
10173                                         USTPUTC(c, out);
10174                                 } else {
10175                                         if (dqvarnest == 0) {
10176                                                 syntax = BASESYNTAX;
10177                                                 dblquote = 0;
10178                                         }
10179                                         quotef = 1;
10180                                         goto quotemark;
10181                                 }
10182                                 break;
10183                         case CVAR:      /* '$' */
10184                                 PARSESUB();             /* parse substitution */
10185                                 break;
10186                         case CENDVAR:   /* '}' */
10187                                 if (varnest > 0) {
10188                                         varnest--;
10189                                         if (dqvarnest > 0) {
10190                                                 dqvarnest--;
10191                                         }
10192                                         USTPUTC(CTLENDVAR, out);
10193                                 } else {
10194                                         USTPUTC(c, out);
10195                                 }
10196                                 break;
10197 #if ENABLE_ASH_MATH_SUPPORT
10198                         case CLP:       /* '(' in arithmetic */
10199                                 parenlevel++;
10200                                 USTPUTC(c, out);
10201                                 break;
10202                         case CRP:       /* ')' in arithmetic */
10203                                 if (parenlevel > 0) {
10204                                         USTPUTC(c, out);
10205                                         --parenlevel;
10206                                 } else {
10207                                         if (pgetc() == ')') {
10208                                                 if (--arinest == 0) {
10209                                                         USTPUTC(CTLENDARI, out);
10210                                                         syntax = prevsyntax;
10211                                                         dblquote = (syntax == DQSYNTAX);
10212                                                 } else
10213                                                         USTPUTC(')', out);
10214                                         } else {
10215                                                 /*
10216                                                  * unbalanced parens
10217                                                  *  (don't 2nd guess - no error)
10218                                                  */
10219                                                 pungetc();
10220                                                 USTPUTC(')', out);
10221                                         }
10222                                 }
10223                                 break;
10224 #endif
10225                         case CBQUOTE:   /* '`' */
10226                                 PARSEBACKQOLD();
10227                                 break;
10228                         case CENDFILE:
10229                                 goto endword;           /* exit outer loop */
10230                         case CIGN:
10231                                 break;
10232                         default:
10233                                 if (varnest == 0)
10234                                         goto endword;   /* exit outer loop */
10235 #if ENABLE_ASH_ALIAS
10236                                 if (c != PEOA)
10237 #endif
10238                                         USTPUTC(c, out);
10239
10240                         }
10241                         c = pgetc_macro();
10242                 }
10243         }
10244  endword:
10245 #if ENABLE_ASH_MATH_SUPPORT
10246         if (syntax == ARISYNTAX)
10247                 raise_error_syntax("Missing '))'");
10248 #endif
10249         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10250                 raise_error_syntax("Unterminated quoted string");
10251         if (varnest != 0) {
10252                 startlinno = plinno;
10253                 /* { */
10254                 raise_error_syntax("Missing '}'");
10255         }
10256         USTPUTC('\0', out);
10257         len = out - (char *)stackblock();
10258         out = stackblock();
10259         if (eofmark == NULL) {
10260                 if ((c == '>' || c == '<')
10261                  && quotef == 0
10262                  && len <= 2
10263                  && (*out == '\0' || isdigit(*out))) {
10264                         PARSEREDIR();
10265                         return lasttoken = TREDIR;
10266                 } else {
10267                         pungetc();
10268                 }
10269         }
10270         quoteflag = quotef;
10271         backquotelist = bqlist;
10272         grabstackblock(len);
10273         wordtext = out;
10274         lasttoken = TWORD;
10275         return lasttoken;
10276 /* end of readtoken routine */
10277
10278 /*
10279  * Check to see whether we are at the end of the here document.  When this
10280  * is called, c is set to the first character of the next input line.  If
10281  * we are at the end of the here document, this routine sets the c to PEOF.
10282  */
10283 checkend: {
10284         if (eofmark) {
10285 #if ENABLE_ASH_ALIAS
10286                 if (c == PEOA) {
10287                         c = pgetc2();
10288                 }
10289 #endif
10290                 if (striptabs) {
10291                         while (c == '\t') {
10292                                 c = pgetc2();
10293                         }
10294                 }
10295                 if (c == *eofmark) {
10296                         if (pfgets(line, sizeof(line)) != NULL) {
10297                                 char *p, *q;
10298
10299                                 p = line;
10300                                 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10301                                 if (*p == '\n' && *q == '\0') {
10302                                         c = PEOF;
10303                                         plinno++;
10304                                         needprompt = doprompt;
10305                                 } else {
10306                                         pushstring(line, NULL);
10307                                 }
10308                         }
10309                 }
10310         }
10311         goto checkend_return;
10312 }
10313
10314 /*
10315  * Parse a redirection operator.  The variable "out" points to a string
10316  * specifying the fd to be redirected.  The variable "c" contains the
10317  * first character of the redirection operator.
10318  */
10319 parseredir: {
10320         char fd = *out;
10321         union node *np;
10322
10323         np = stzalloc(sizeof(struct nfile));
10324         if (c == '>') {
10325                 np->nfile.fd = 1;
10326                 c = pgetc();
10327                 if (c == '>')
10328                         np->type = NAPPEND;
10329                 else if (c == '|')
10330                         np->type = NCLOBBER;
10331                 else if (c == '&')
10332                         np->type = NTOFD;
10333                 else {
10334                         np->type = NTO;
10335                         pungetc();
10336                 }
10337         } else {        /* c == '<' */
10338                 /*np->nfile.fd = 0; - stzalloc did it */
10339                 c = pgetc();
10340                 switch (c) {
10341                 case '<':
10342                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10343                                 np = stzalloc(sizeof(struct nhere));
10344                                 /*np->nfile.fd = 0; - stzalloc did it */
10345                         }
10346                         np->type = NHERE;
10347                         heredoc = stalloc(sizeof(struct heredoc));
10348                         heredoc->here = np;
10349                         c = pgetc();
10350                         if (c == '-') {
10351                                 heredoc->striptabs = 1;
10352                         } else {
10353                                 heredoc->striptabs = 0;
10354                                 pungetc();
10355                         }
10356                         break;
10357
10358                 case '&':
10359                         np->type = NFROMFD;
10360                         break;
10361
10362                 case '>':
10363                         np->type = NFROMTO;
10364                         break;
10365
10366                 default:
10367                         np->type = NFROM;
10368                         pungetc();
10369                         break;
10370                 }
10371         }
10372         if (fd != '\0')
10373                 np->nfile.fd = fd - '0';
10374         redirnode = np;
10375         goto parseredir_return;
10376 }
10377
10378 /*
10379  * Parse a substitution.  At this point, we have read the dollar sign
10380  * and nothing else.
10381  */
10382
10383 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10384  * (assuming ascii char codes, as the original implementation did) */
10385 #define is_special(c) \
10386         ((((unsigned int)c) - 33 < 32) \
10387                         && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10388 parsesub: {
10389         int subtype;
10390         int typeloc;
10391         int flags;
10392         char *p;
10393         static const char types[] ALIGN1 = "}-+?=";
10394
10395         c = pgetc();
10396         if (
10397                 c <= PEOA_OR_PEOF  ||
10398                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10399         ) {
10400                 USTPUTC('$', out);
10401                 pungetc();
10402         } else if (c == '(') {  /* $(command) or $((arith)) */
10403                 if (pgetc() == '(') {
10404 #if ENABLE_ASH_MATH_SUPPORT
10405                         PARSEARITH();
10406 #else
10407                         raise_error_syntax("We unsupport $((arith))");
10408 #endif
10409                 } else {
10410                         pungetc();
10411                         PARSEBACKQNEW();
10412                 }
10413         } else {
10414                 USTPUTC(CTLVAR, out);
10415                 typeloc = out - (char *)stackblock();
10416                 USTPUTC(VSNORMAL, out);
10417                 subtype = VSNORMAL;
10418                 if (c == '{') {
10419                         c = pgetc();
10420                         if (c == '#') {
10421                                 c = pgetc();
10422                                 if (c == '}')
10423                                         c = '#';
10424                                 else
10425                                         subtype = VSLENGTH;
10426                         } else
10427                                 subtype = 0;
10428                 }
10429                 if (c > PEOA_OR_PEOF && is_name(c)) {
10430                         do {
10431                                 STPUTC(c, out);
10432                                 c = pgetc();
10433                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10434                 } else if (isdigit(c)) {
10435                         do {
10436                                 STPUTC(c, out);
10437                                 c = pgetc();
10438                         } while (isdigit(c));
10439                 } else if (is_special(c)) {
10440                         USTPUTC(c, out);
10441                         c = pgetc();
10442                 } else
10443  badsub:                raise_error_syntax("Bad substitution");
10444
10445                 STPUTC('=', out);
10446                 flags = 0;
10447                 if (subtype == 0) {
10448                         switch (c) {
10449                         case ':':
10450                                 flags = VSNUL;
10451                                 c = pgetc();
10452                                 /*FALLTHROUGH*/
10453                         default:
10454                                 p = strchr(types, c);
10455                                 if (p == NULL)
10456                                         goto badsub;
10457                                 subtype = p - types + VSNORMAL;
10458                                 break;
10459                         case '%':
10460                         case '#':
10461                                 {
10462                                         int cc = c;
10463                                         subtype = c == '#' ? VSTRIMLEFT :
10464                                                              VSTRIMRIGHT;
10465                                         c = pgetc();
10466                                         if (c == cc)
10467                                                 subtype++;
10468                                         else
10469                                                 pungetc();
10470                                         break;
10471                                 }
10472                         }
10473                 } else {
10474                         pungetc();
10475                 }
10476                 if (dblquote || arinest)
10477                         flags |= VSQUOTE;
10478                 *((char *)stackblock() + typeloc) = subtype | flags;
10479                 if (subtype != VSNORMAL) {
10480                         varnest++;
10481                         if (dblquote || arinest) {
10482                                 dqvarnest++;
10483                         }
10484                 }
10485         }
10486         goto parsesub_return;
10487 }
10488
10489 /*
10490  * Called to parse command substitutions.  Newstyle is set if the command
10491  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10492  * list of commands (passed by reference), and savelen is the number of
10493  * characters on the top of the stack which must be preserved.
10494  */
10495 parsebackq: {
10496         struct nodelist **nlpp;
10497         smallint savepbq;
10498         union node *n;
10499         char *volatile str;
10500         struct jmploc jmploc;
10501         struct jmploc *volatile savehandler;
10502         size_t savelen;
10503         smallint saveprompt = 0;
10504
10505 #ifdef __GNUC__
10506         (void) &saveprompt;
10507 #endif
10508         savepbq = parsebackquote;
10509         if (setjmp(jmploc.loc)) {
10510                 free(str);
10511                 parsebackquote = 0;
10512                 exception_handler = savehandler;
10513                 longjmp(exception_handler->loc, 1);
10514         }
10515         INT_OFF;
10516         str = NULL;
10517         savelen = out - (char *)stackblock();
10518         if (savelen > 0) {
10519                 str = ckmalloc(savelen);
10520                 memcpy(str, stackblock(), savelen);
10521         }
10522         savehandler = exception_handler;
10523         exception_handler = &jmploc;
10524         INT_ON;
10525         if (oldstyle) {
10526                 /* We must read until the closing backquote, giving special
10527                    treatment to some slashes, and then push the string and
10528                    reread it as input, interpreting it normally.  */
10529                 char *pout;
10530                 int pc;
10531                 size_t psavelen;
10532                 char *pstr;
10533
10534
10535                 STARTSTACKSTR(pout);
10536                 for (;;) {
10537                         if (needprompt) {
10538                                 setprompt(2);
10539                         }
10540                         pc = pgetc();
10541                         switch (pc) {
10542                         case '`':
10543                                 goto done;
10544
10545                         case '\\':
10546                                 pc = pgetc();
10547                                 if (pc == '\n') {
10548                                         plinno++;
10549                                         if (doprompt)
10550                                                 setprompt(2);
10551                                         /*
10552                                          * If eating a newline, avoid putting
10553                                          * the newline into the new character
10554                                          * stream (via the STPUTC after the
10555                                          * switch).
10556                                          */
10557                                         continue;
10558                                 }
10559                                 if (pc != '\\' && pc != '`' && pc != '$'
10560                                  && (!dblquote || pc != '"'))
10561                                         STPUTC('\\', pout);
10562                                 if (pc > PEOA_OR_PEOF) {
10563                                         break;
10564                                 }
10565                                 /* fall through */
10566
10567                         case PEOF:
10568 #if ENABLE_ASH_ALIAS
10569                         case PEOA:
10570 #endif
10571                                 startlinno = plinno;
10572                                 raise_error_syntax("EOF in backquote substitution");
10573
10574                         case '\n':
10575                                 plinno++;
10576                                 needprompt = doprompt;
10577                                 break;
10578
10579                         default:
10580                                 break;
10581                         }
10582                         STPUTC(pc, pout);
10583                 }
10584  done:
10585                 STPUTC('\0', pout);
10586                 psavelen = pout - (char *)stackblock();
10587                 if (psavelen > 0) {
10588                         pstr = grabstackstr(pout);
10589                         setinputstring(pstr);
10590                 }
10591         }
10592         nlpp = &bqlist;
10593         while (*nlpp)
10594                 nlpp = &(*nlpp)->next;
10595         *nlpp = stzalloc(sizeof(**nlpp));
10596         /* (*nlpp)->next = NULL; - stzalloc did it */
10597         parsebackquote = oldstyle;
10598
10599         if (oldstyle) {
10600                 saveprompt = doprompt;
10601                 doprompt = 0;
10602         }
10603
10604         n = list(2);
10605
10606         if (oldstyle)
10607                 doprompt = saveprompt;
10608         else if (readtoken() != TRP)
10609                 raise_error_unexpected_syntax(TRP);
10610
10611         (*nlpp)->n = n;
10612         if (oldstyle) {
10613                 /*
10614                  * Start reading from old file again, ignoring any pushed back
10615                  * tokens left from the backquote parsing
10616                  */
10617                 popfile();
10618                 tokpushback = 0;
10619         }
10620         while (stackblocksize() <= savelen)
10621                 growstackblock();
10622         STARTSTACKSTR(out);
10623         if (str) {
10624                 memcpy(out, str, savelen);
10625                 STADJUST(savelen, out);
10626                 INT_OFF;
10627                 free(str);
10628                 str = NULL;
10629                 INT_ON;
10630         }
10631         parsebackquote = savepbq;
10632         exception_handler = savehandler;
10633         if (arinest || dblquote)
10634                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10635         else
10636                 USTPUTC(CTLBACKQ, out);
10637         if (oldstyle)
10638                 goto parsebackq_oldreturn;
10639         goto parsebackq_newreturn;
10640 }
10641
10642 #if ENABLE_ASH_MATH_SUPPORT
10643 /*
10644  * Parse an arithmetic expansion (indicate start of one and set state)
10645  */
10646 parsearith: {
10647         if (++arinest == 1) {
10648                 prevsyntax = syntax;
10649                 syntax = ARISYNTAX;
10650                 USTPUTC(CTLARI, out);
10651                 if (dblquote)
10652                         USTPUTC('"', out);
10653                 else
10654                         USTPUTC(' ', out);
10655         } else {
10656                 /*
10657                  * we collapse embedded arithmetic expansion to
10658                  * parenthesis, which should be equivalent
10659                  */
10660                 USTPUTC('(', out);
10661         }
10662         goto parsearith_return;
10663 }
10664 #endif
10665
10666 } /* end of readtoken */
10667
10668 /*
10669  * Read the next input token.
10670  * If the token is a word, we set backquotelist to the list of cmds in
10671  *      backquotes.  We set quoteflag to true if any part of the word was
10672  *      quoted.
10673  * If the token is TREDIR, then we set redirnode to a structure containing
10674  *      the redirection.
10675  * In all cases, the variable startlinno is set to the number of the line
10676  *      on which the token starts.
10677  *
10678  * [Change comment:  here documents and internal procedures]
10679  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10680  *  word parsing code into a separate routine.  In this case, readtoken
10681  *  doesn't need to have any internal procedures, but parseword does.
10682  *  We could also make parseoperator in essence the main routine, and
10683  *  have parseword (readtoken1?) handle both words and redirection.]
10684  */
10685 #define NEW_xxreadtoken
10686 #ifdef NEW_xxreadtoken
10687 /* singles must be first! */
10688 static const char xxreadtoken_chars[7] ALIGN1 = {
10689         '\n', '(', ')', '&', '|', ';', 0
10690 };
10691
10692 static const char xxreadtoken_tokens[] ALIGN1 = {
10693         TNL, TLP, TRP,          /* only single occurrence allowed */
10694         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10695         TEOF,                   /* corresponds to trailing nul */
10696         TAND, TOR, TENDCASE     /* if double occurrence */
10697 };
10698
10699 #define xxreadtoken_doubles \
10700         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10701 #define xxreadtoken_singles \
10702         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10703
10704 static int
10705 xxreadtoken(void)
10706 {
10707         int c;
10708
10709         if (tokpushback) {
10710                 tokpushback = 0;
10711                 return lasttoken;
10712         }
10713         if (needprompt) {
10714                 setprompt(2);
10715         }
10716         startlinno = plinno;
10717         for (;;) {                      /* until token or start of word found */
10718                 c = pgetc_macro();
10719
10720                 if ((c != ' ') && (c != '\t')
10721 #if ENABLE_ASH_ALIAS
10722                  && (c != PEOA)
10723 #endif
10724                 ) {
10725                         if (c == '#') {
10726                                 while ((c = pgetc()) != '\n' && c != PEOF);
10727                                 pungetc();
10728                         } else if (c == '\\') {
10729                                 if (pgetc() != '\n') {
10730                                         pungetc();
10731                                         goto READTOKEN1;
10732                                 }
10733                                 startlinno = ++plinno;
10734                                 if (doprompt)
10735                                         setprompt(2);
10736                         } else {
10737                                 const char *p
10738                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10739
10740                                 if (c != PEOF) {
10741                                         if (c == '\n') {
10742                                                 plinno++;
10743                                                 needprompt = doprompt;
10744                                         }
10745
10746                                         p = strchr(xxreadtoken_chars, c);
10747                                         if (p == NULL) {
10748  READTOKEN1:
10749                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10750                                         }
10751
10752                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10753                                                 if (pgetc() == *p) {    /* double occurrence? */
10754                                                         p += xxreadtoken_doubles + 1;
10755                                                 } else {
10756                                                         pungetc();
10757                                                 }
10758                                         }
10759                                 }
10760                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10761                         }
10762                 }
10763         } /* for */
10764 }
10765 #else
10766 #define RETURN(token)   return lasttoken = token
10767 static int
10768 xxreadtoken(void)
10769 {
10770         int c;
10771
10772         if (tokpushback) {
10773                 tokpushback = 0;
10774                 return lasttoken;
10775         }
10776         if (needprompt) {
10777                 setprompt(2);
10778         }
10779         startlinno = plinno;
10780         for (;;) {      /* until token or start of word found */
10781                 c = pgetc_macro();
10782                 switch (c) {
10783                 case ' ': case '\t':
10784 #if ENABLE_ASH_ALIAS
10785                 case PEOA:
10786 #endif
10787                         continue;
10788                 case '#':
10789                         while ((c = pgetc()) != '\n' && c != PEOF);
10790                         pungetc();
10791                         continue;
10792                 case '\\':
10793                         if (pgetc() == '\n') {
10794                                 startlinno = ++plinno;
10795                                 if (doprompt)
10796                                         setprompt(2);
10797                                 continue;
10798                         }
10799                         pungetc();
10800                         goto breakloop;
10801                 case '\n':
10802                         plinno++;
10803                         needprompt = doprompt;
10804                         RETURN(TNL);
10805                 case PEOF:
10806                         RETURN(TEOF);
10807                 case '&':
10808                         if (pgetc() == '&')
10809                                 RETURN(TAND);
10810                         pungetc();
10811                         RETURN(TBACKGND);
10812                 case '|':
10813                         if (pgetc() == '|')
10814                                 RETURN(TOR);
10815                         pungetc();
10816                         RETURN(TPIPE);
10817                 case ';':
10818                         if (pgetc() == ';')
10819                                 RETURN(TENDCASE);
10820                         pungetc();
10821                         RETURN(TSEMI);
10822                 case '(':
10823                         RETURN(TLP);
10824                 case ')':
10825                         RETURN(TRP);
10826                 default:
10827                         goto breakloop;
10828                 }
10829         }
10830  breakloop:
10831         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10832 #undef RETURN
10833 }
10834 #endif /* NEW_xxreadtoken */
10835
10836 static int
10837 readtoken(void)
10838 {
10839         int t;
10840 #if DEBUG
10841         smallint alreadyseen = tokpushback;
10842 #endif
10843
10844 #if ENABLE_ASH_ALIAS
10845  top:
10846 #endif
10847
10848         t = xxreadtoken();
10849
10850         /*
10851          * eat newlines
10852          */
10853         if (checkkwd & CHKNL) {
10854                 while (t == TNL) {
10855                         parseheredoc();
10856                         t = xxreadtoken();
10857                 }
10858         }
10859
10860         if (t != TWORD || quoteflag) {
10861                 goto out;
10862         }
10863
10864         /*
10865          * check for keywords
10866          */
10867         if (checkkwd & CHKKWD) {
10868                 const char *const *pp;
10869
10870                 pp = findkwd(wordtext);
10871                 if (pp) {
10872                         lasttoken = t = pp - tokname_array;
10873                         TRACE(("keyword %s recognized\n", tokname(t)));
10874                         goto out;
10875                 }
10876         }
10877
10878         if (checkkwd & CHKALIAS) {
10879 #if ENABLE_ASH_ALIAS
10880                 struct alias *ap;
10881                 ap = lookupalias(wordtext, 1);
10882                 if (ap != NULL) {
10883                         if (*ap->val) {
10884                                 pushstring(ap->val, ap);
10885                         }
10886                         goto top;
10887                 }
10888 #endif
10889         }
10890  out:
10891         checkkwd = 0;
10892 #if DEBUG
10893         if (!alreadyseen)
10894                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10895         else
10896                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10897 #endif
10898         return t;
10899 }
10900
10901 static char
10902 peektoken(void)
10903 {
10904         int t;
10905
10906         t = readtoken();
10907         tokpushback = 1;
10908         return tokname_array[t][0];
10909 }
10910
10911 /*
10912  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
10913  * valid parse tree indicating a blank line.)
10914  */
10915 static union node *
10916 parsecmd(int interact)
10917 {
10918         int t;
10919
10920         tokpushback = 0;
10921         doprompt = interact;
10922         if (doprompt)
10923                 setprompt(doprompt);
10924         needprompt = 0;
10925         t = readtoken();
10926         if (t == TEOF)
10927                 return NEOF;
10928         if (t == TNL)
10929                 return NULL;
10930         tokpushback = 1;
10931         return list(1);
10932 }
10933
10934 /*
10935  * Input any here documents.
10936  */
10937 static void
10938 parseheredoc(void)
10939 {
10940         struct heredoc *here;
10941         union node *n;
10942
10943         here = heredoclist;
10944         heredoclist = 0;
10945
10946         while (here) {
10947                 if (needprompt) {
10948                         setprompt(2);
10949                 }
10950                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10951                                 here->eofmark, here->striptabs);
10952                 n = stzalloc(sizeof(struct narg));
10953                 n->narg.type = NARG;
10954                 /*n->narg.next = NULL; - stzalloc did it */
10955                 n->narg.text = wordtext;
10956                 n->narg.backquote = backquotelist;
10957                 here->here->nhere.doc = n;
10958                 here = here->next;
10959         }
10960 }
10961
10962
10963 /*
10964  * called by editline -- any expansions to the prompt should be added here.
10965  */
10966 #if ENABLE_ASH_EXPAND_PRMT
10967 static const char *
10968 expandstr(const char *ps)
10969 {
10970         union node n;
10971
10972         /* XXX Fix (char *) cast. */
10973         setinputstring((char *)ps);
10974         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
10975         popfile();
10976
10977         n.narg.type = NARG;
10978         n.narg.next = NULL;
10979         n.narg.text = wordtext;
10980         n.narg.backquote = backquotelist;
10981
10982         expandarg(&n, NULL, 0);
10983         return stackblock();
10984 }
10985 #endif
10986
10987 /*
10988  * Execute a command or commands contained in a string.
10989  */
10990 static int
10991 evalstring(char *s, int mask)
10992 {
10993         union node *n;
10994         struct stackmark smark;
10995         int skip;
10996
10997         setinputstring(s);
10998         setstackmark(&smark);
10999
11000         skip = 0;
11001         while ((n = parsecmd(0)) != NEOF) {
11002                 evaltree(n, 0);
11003                 popstackmark(&smark);
11004                 skip = evalskip;
11005                 if (skip)
11006                         break;
11007         }
11008         popfile();
11009
11010         skip &= mask;
11011         evalskip = skip;
11012         return skip;
11013 }
11014
11015 /*
11016  * The eval command.
11017  */
11018 static int
11019 evalcmd(int argc, char **argv)
11020 {
11021         char *p;
11022         char *concat;
11023         char **ap;
11024
11025         if (argc > 1) {
11026                 p = argv[1];
11027                 if (argc > 2) {
11028                         STARTSTACKSTR(concat);
11029                         ap = argv + 2;
11030                         for (;;) {
11031                                 concat = stack_putstr(p, concat);
11032                                 p = *ap++;
11033                                 if (p == NULL)
11034                                         break;
11035                                 STPUTC(' ', concat);
11036                         }
11037                         STPUTC('\0', concat);
11038                         p = grabstackstr(concat);
11039                 }
11040                 evalstring(p, ~SKIPEVAL);
11041
11042         }
11043         return exitstatus;
11044 }
11045
11046 /*
11047  * Read and execute commands.  "Top" is nonzero for the top level command
11048  * loop; it turns on prompting if the shell is interactive.
11049  */
11050 static int
11051 cmdloop(int top)
11052 {
11053         union node *n;
11054         struct stackmark smark;
11055         int inter;
11056         int numeof = 0;
11057
11058         TRACE(("cmdloop(%d) called\n", top));
11059         for (;;) {
11060                 int skip;
11061
11062                 setstackmark(&smark);
11063 #if JOBS
11064                 if (jobctl)
11065                         showjobs(stderr, SHOW_CHANGED);
11066 #endif
11067                 inter = 0;
11068                 if (iflag && top) {
11069                         inter++;
11070 #if ENABLE_ASH_MAIL
11071                         chkmail();
11072 #endif
11073                 }
11074                 n = parsecmd(inter);
11075                 /* showtree(n); DEBUG */
11076                 if (n == NEOF) {
11077                         if (!top || numeof >= 50)
11078                                 break;
11079                         if (!stoppedjobs()) {
11080                                 if (!Iflag)
11081                                         break;
11082                                 out2str("\nUse \"exit\" to leave shell.\n");
11083                         }
11084                         numeof++;
11085                 } else if (nflag == 0) {
11086                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11087                         job_warning >>= 1;
11088                         numeof = 0;
11089                         evaltree(n, 0);
11090                 }
11091                 popstackmark(&smark);
11092                 skip = evalskip;
11093
11094                 if (skip) {
11095                         evalskip = 0;
11096                         return skip & SKIPEVAL;
11097                 }
11098         }
11099         return 0;
11100 }
11101
11102 /*
11103  * Take commands from a file.  To be compatible we should do a path
11104  * search for the file, which is necessary to find sub-commands.
11105  */
11106 static char *
11107 find_dot_file(char *name)
11108 {
11109         char *fullname;
11110         const char *path = pathval();
11111         struct stat statb;
11112
11113         /* don't try this for absolute or relative paths */
11114         if (strchr(name, '/'))
11115                 return name;
11116
11117         while ((fullname = padvance(&path, name)) != NULL) {
11118                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11119                         /*
11120                          * Don't bother freeing here, since it will
11121                          * be freed by the caller.
11122                          */
11123                         return fullname;
11124                 }
11125                 stunalloc(fullname);
11126         }
11127
11128         /* not found in the PATH */
11129         ash_msg_and_raise_error("%s: not found", name);
11130         /* NOTREACHED */
11131 }
11132
11133 static int
11134 dotcmd(int argc, char **argv)
11135 {
11136         struct strlist *sp;
11137         volatile struct shparam saveparam;
11138         int status = 0;
11139
11140         for (sp = cmdenviron; sp; sp = sp->next)
11141                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11142
11143         if (argc >= 2) {        /* That's what SVR2 does */
11144                 char *fullname;
11145
11146                 fullname = find_dot_file(argv[1]);
11147
11148                 if (argc > 2) {
11149                         saveparam = shellparam;
11150                         shellparam.malloced = 0;
11151                         shellparam.nparam = argc - 2;
11152                         shellparam.p = argv + 2;
11153                 };
11154
11155                 setinputfile(fullname, INPUT_PUSH_FILE);
11156                 commandname = fullname;
11157                 cmdloop(0);
11158                 popfile();
11159
11160                 if (argc > 2) {
11161                         freeparam(&shellparam);
11162                         shellparam = saveparam;
11163                 };
11164                 status = exitstatus;
11165         }
11166         return status;
11167 }
11168
11169 static int
11170 exitcmd(int argc, char **argv)
11171 {
11172         if (stoppedjobs())
11173                 return 0;
11174         if (argc > 1)
11175                 exitstatus = number(argv[1]);
11176         raise_exception(EXEXIT);
11177         /* NOTREACHED */
11178 }
11179
11180 #if ENABLE_ASH_BUILTIN_ECHO
11181 static int
11182 echocmd(int argc, char **argv)
11183 {
11184         return echo_main(argc, argv);
11185 }
11186 #endif
11187
11188 #if ENABLE_ASH_BUILTIN_TEST
11189 static int
11190 testcmd(int argc, char **argv)
11191 {
11192         return test_main(argc, argv);
11193 }
11194 #endif
11195
11196 /*
11197  * Read a file containing shell functions.
11198  */
11199 static void
11200 readcmdfile(char *name)
11201 {
11202         setinputfile(name, INPUT_PUSH_FILE);
11203         cmdloop(0);
11204         popfile();
11205 }
11206
11207
11208 /* ============ find_command inplementation */
11209
11210 /*
11211  * Resolve a command name.  If you change this routine, you may have to
11212  * change the shellexec routine as well.
11213  */
11214 static void
11215 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11216 {
11217         struct tblentry *cmdp;
11218         int idx;
11219         int prev;
11220         char *fullname;
11221         struct stat statb;
11222         int e;
11223         int updatetbl;
11224         struct builtincmd *bcmd;
11225
11226         /* If name contains a slash, don't use PATH or hash table */
11227         if (strchr(name, '/') != NULL) {
11228                 entry->u.index = -1;
11229                 if (act & DO_ABS) {
11230                         while (stat(name, &statb) < 0) {
11231 #ifdef SYSV
11232                                 if (errno == EINTR)
11233                                         continue;
11234 #endif
11235                                 entry->cmdtype = CMDUNKNOWN;
11236                                 return;
11237                         }
11238                 }
11239                 entry->cmdtype = CMDNORMAL;
11240                 return;
11241         }
11242
11243 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11244
11245         updatetbl = (path == pathval());
11246         if (!updatetbl) {
11247                 act |= DO_ALTPATH;
11248                 if (strstr(path, "%builtin") != NULL)
11249                         act |= DO_ALTBLTIN;
11250         }
11251
11252         /* If name is in the table, check answer will be ok */
11253         cmdp = cmdlookup(name, 0);
11254         if (cmdp != NULL) {
11255                 int bit;
11256
11257                 switch (cmdp->cmdtype) {
11258                 default:
11259 #if DEBUG
11260                         abort();
11261 #endif
11262                 case CMDNORMAL:
11263                         bit = DO_ALTPATH;
11264                         break;
11265                 case CMDFUNCTION:
11266                         bit = DO_NOFUNC;
11267                         break;
11268                 case CMDBUILTIN:
11269                         bit = DO_ALTBLTIN;
11270                         break;
11271                 }
11272                 if (act & bit) {
11273                         updatetbl = 0;
11274                         cmdp = NULL;
11275                 } else if (cmdp->rehash == 0)
11276                         /* if not invalidated by cd, we're done */
11277                         goto success;
11278         }
11279
11280         /* If %builtin not in path, check for builtin next */
11281         bcmd = find_builtin(name);
11282         if (bcmd) {
11283                 if (IS_BUILTIN_REGULAR(bcmd))
11284                         goto builtin_success;
11285                 if (act & DO_ALTPATH) {
11286                         if (!(act & DO_ALTBLTIN))
11287                                 goto builtin_success;
11288                 } else if (builtinloc <= 0) {
11289                         goto builtin_success;
11290                 }
11291         }
11292
11293 #if ENABLE_FEATURE_SH_STANDALONE
11294         if (find_applet_by_name(name) >= 0) {
11295                 entry->cmdtype = CMDNORMAL;
11296                 entry->u.index = -1;
11297                 return;
11298         }
11299 #endif
11300
11301         /* We have to search path. */
11302         prev = -1;              /* where to start */
11303         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11304                 if (cmdp->cmdtype == CMDBUILTIN)
11305                         prev = builtinloc;
11306                 else
11307                         prev = cmdp->param.index;
11308         }
11309
11310         e = ENOENT;
11311         idx = -1;
11312  loop:
11313         while ((fullname = padvance(&path, name)) != NULL) {
11314                 stunalloc(fullname);
11315                 /* NB: code below will still use fullname
11316                  * despite it being "unallocated" */
11317                 idx++;
11318                 if (pathopt) {
11319                         if (prefix(pathopt, "builtin")) {
11320                                 if (bcmd)
11321                                         goto builtin_success;
11322                                 continue;
11323                         } else if (!(act & DO_NOFUNC)
11324                          && prefix(pathopt, "func")) {
11325                                 /* handled below */
11326                         } else {
11327                                 /* ignore unimplemented options */
11328                                 continue;
11329                         }
11330                 }
11331                 /* if rehash, don't redo absolute path names */
11332                 if (fullname[0] == '/' && idx <= prev) {
11333                         if (idx < prev)
11334                                 continue;
11335                         TRACE(("searchexec \"%s\": no change\n", name));
11336                         goto success;
11337                 }
11338                 while (stat(fullname, &statb) < 0) {
11339 #ifdef SYSV
11340                         if (errno == EINTR)
11341                                 continue;
11342 #endif
11343                         if (errno != ENOENT && errno != ENOTDIR)
11344                                 e = errno;
11345                         goto loop;
11346                 }
11347                 e = EACCES;     /* if we fail, this will be the error */
11348                 if (!S_ISREG(statb.st_mode))
11349                         continue;
11350                 if (pathopt) {          /* this is a %func directory */
11351                         stalloc(strlen(fullname) + 1);
11352                         /* NB: stalloc will return space pointed by fullname
11353                          * (because we don't have any intervening allocations
11354                          * between stunalloc above and this stalloc) */
11355                         readcmdfile(fullname);
11356                         cmdp = cmdlookup(name, 0);
11357                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11358                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11359                         stunalloc(fullname);
11360                         goto success;
11361                 }
11362                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11363                 if (!updatetbl) {
11364                         entry->cmdtype = CMDNORMAL;
11365                         entry->u.index = idx;
11366                         return;
11367                 }
11368                 INT_OFF;
11369                 cmdp = cmdlookup(name, 1);
11370                 cmdp->cmdtype = CMDNORMAL;
11371                 cmdp->param.index = idx;
11372                 INT_ON;
11373                 goto success;
11374         }
11375
11376         /* We failed.  If there was an entry for this command, delete it */
11377         if (cmdp && updatetbl)
11378                 delete_cmd_entry();
11379         if (act & DO_ERR)
11380                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11381         entry->cmdtype = CMDUNKNOWN;
11382         return;
11383
11384  builtin_success:
11385         if (!updatetbl) {
11386                 entry->cmdtype = CMDBUILTIN;
11387                 entry->u.cmd = bcmd;
11388                 return;
11389         }
11390         INT_OFF;
11391         cmdp = cmdlookup(name, 1);
11392         cmdp->cmdtype = CMDBUILTIN;
11393         cmdp->param.cmd = bcmd;
11394         INT_ON;
11395  success:
11396         cmdp->rehash = 0;
11397         entry->cmdtype = cmdp->cmdtype;
11398         entry->u = cmdp->param;
11399 }
11400
11401
11402 /* ============ trap.c */
11403
11404 /*
11405  * The trap builtin.
11406  */
11407 static int
11408 trapcmd(int argc, char **argv)
11409 {
11410         char *action;
11411         char **ap;
11412         int signo;
11413
11414         nextopt(nullstr);
11415         ap = argptr;
11416         if (!*ap) {
11417                 for (signo = 0; signo < NSIG; signo++) {
11418                         if (trap[signo] != NULL) {
11419                                 const char *sn;
11420
11421                                 sn = get_signame(signo);
11422                                 out1fmt("trap -- %s %s\n",
11423                                         single_quote(trap[signo]), sn);
11424                         }
11425                 }
11426                 return 0;
11427         }
11428         if (!ap[1])
11429                 action = NULL;
11430         else
11431                 action = *ap++;
11432         while (*ap) {
11433                 signo = get_signum(*ap);
11434                 if (signo < 0)
11435                         ash_msg_and_raise_error("%s: bad trap", *ap);
11436                 INT_OFF;
11437                 if (action) {
11438                         if (LONE_DASH(action))
11439                                 action = NULL;
11440                         else
11441                                 action = ckstrdup(action);
11442                 }
11443                 free(trap[signo]);
11444                 trap[signo] = action;
11445                 if (signo != 0)
11446                         setsignal(signo);
11447                 INT_ON;
11448                 ap++;
11449         }
11450         return 0;
11451 }
11452
11453
11454 /* ============ Builtins */
11455
11456 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11457 /*
11458  * Lists available builtins
11459  */
11460 static int
11461 helpcmd(int argc, char **argv)
11462 {
11463         int col, i;
11464
11465         out1fmt("\nBuilt-in commands:\n-------------------\n");
11466         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11467                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11468                                         builtintab[i].name + 1);
11469                 if (col > 60) {
11470                         out1fmt("\n");
11471                         col = 0;
11472                 }
11473         }
11474 #if ENABLE_FEATURE_SH_STANDALONE
11475         {
11476                 const char *a = applet_names;
11477                 while (*a) {
11478                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11479                         if (col > 60) {
11480                                 out1fmt("\n");
11481                                 col = 0;
11482                         }
11483                         a += strlen(a) + 1;
11484                 }
11485         }
11486 #endif
11487         out1fmt("\n\n");
11488         return EXIT_SUCCESS;
11489 }
11490 #endif /* FEATURE_SH_EXTRA_QUIET */
11491
11492 /*
11493  * The export and readonly commands.
11494  */
11495 static int
11496 exportcmd(int argc, char **argv)
11497 {
11498         struct var *vp;
11499         char *name;
11500         const char *p;
11501         char **aptr;
11502         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11503
11504         if (nextopt("p") != 'p') {
11505                 aptr = argptr;
11506                 name = *aptr;
11507                 if (name) {
11508                         do {
11509                                 p = strchr(name, '=');
11510                                 if (p != NULL) {
11511                                         p++;
11512                                 } else {
11513                                         vp = *findvar(hashvar(name), name);
11514                                         if (vp) {
11515                                                 vp->flags |= flag;
11516                                                 continue;
11517                                         }
11518                                 }
11519                                 setvar(name, p, flag);
11520                         } while ((name = *++aptr) != NULL);
11521                         return 0;
11522                 }
11523         }
11524         showvars(argv[0], flag, 0);
11525         return 0;
11526 }
11527
11528 /*
11529  * Delete a function if it exists.
11530  */
11531 static void
11532 unsetfunc(const char *name)
11533 {
11534         struct tblentry *cmdp;
11535
11536         cmdp = cmdlookup(name, 0);
11537         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11538                 delete_cmd_entry();
11539 }
11540
11541 /*
11542  * The unset builtin command.  We unset the function before we unset the
11543  * variable to allow a function to be unset when there is a readonly variable
11544  * with the same name.
11545  */
11546 static int
11547 unsetcmd(int argc, char **argv)
11548 {
11549         char **ap;
11550         int i;
11551         int flag = 0;
11552         int ret = 0;
11553
11554         while ((i = nextopt("vf")) != '\0') {
11555                 flag = i;
11556         }
11557
11558         for (ap = argptr; *ap; ap++) {
11559                 if (flag != 'f') {
11560                         i = unsetvar(*ap);
11561                         ret |= i;
11562                         if (!(i & 2))
11563                                 continue;
11564                 }
11565                 if (flag != 'v')
11566                         unsetfunc(*ap);
11567         }
11568         return ret & 1;
11569 }
11570
11571
11572 /*      setmode.c      */
11573
11574 #include <sys/times.h>
11575
11576 static const unsigned char timescmd_str[] ALIGN1 = {
11577         ' ',  offsetof(struct tms, tms_utime),
11578         '\n', offsetof(struct tms, tms_stime),
11579         ' ',  offsetof(struct tms, tms_cutime),
11580         '\n', offsetof(struct tms, tms_cstime),
11581         0
11582 };
11583
11584 static int
11585 timescmd(int ac, char **av)
11586 {
11587         long clk_tck, s, t;
11588         const unsigned char *p;
11589         struct tms buf;
11590
11591         clk_tck = sysconf(_SC_CLK_TCK);
11592         times(&buf);
11593
11594         p = timescmd_str;
11595         do {
11596                 t = *(clock_t *)(((char *) &buf) + p[1]);
11597                 s = t / clk_tck;
11598                 out1fmt("%ldm%ld.%.3lds%c",
11599                         s/60, s%60,
11600                         ((t - s * clk_tck) * 1000) / clk_tck,
11601                         p[0]);
11602         } while (*(p += 2));
11603
11604         return 0;
11605 }
11606
11607 #if ENABLE_ASH_MATH_SUPPORT
11608 static arith_t
11609 dash_arith(const char *s)
11610 {
11611         arith_t result;
11612         int errcode = 0;
11613
11614         INT_OFF;
11615         result = arith(s, &errcode);
11616         if (errcode < 0) {
11617                 if (errcode == -3)
11618                         ash_msg_and_raise_error("exponent less than 0");
11619                 if (errcode == -2)
11620                         ash_msg_and_raise_error("divide by zero");
11621                 if (errcode == -5)
11622                         ash_msg_and_raise_error("expression recursion loop detected");
11623                 raise_error_syntax(s);
11624         }
11625         INT_ON;
11626
11627         return result;
11628 }
11629
11630 /*
11631  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11632  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11633  *
11634  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11635  */
11636 static int
11637 letcmd(int argc, char **argv)
11638 {
11639         char **ap;
11640         arith_t i = 0;
11641
11642         ap = argv + 1;
11643         if (!*ap)
11644                 ash_msg_and_raise_error("expression expected");
11645         for (ap = argv + 1; *ap; ap++) {
11646                 i = dash_arith(*ap);
11647         }
11648
11649         return !i;
11650 }
11651 #endif /* ASH_MATH_SUPPORT */
11652
11653
11654 /* ============ miscbltin.c
11655  *
11656  * Miscellaneous builtins.
11657  */
11658
11659 #undef rflag
11660
11661 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11662 typedef enum __rlimit_resource rlim_t;
11663 #endif
11664
11665 /*
11666  * The read builtin.  The -e option causes backslashes to escape the
11667  * following character.
11668  *
11669  * This uses unbuffered input, which may be avoidable in some cases.
11670  */
11671 static int
11672 readcmd(int argc, char **argv)
11673 {
11674         char **ap;
11675         int backslash;
11676         char c;
11677         int rflag;
11678         char *prompt;
11679         const char *ifs;
11680         char *p;
11681         int startword;
11682         int status;
11683         int i;
11684 #if ENABLE_ASH_READ_NCHARS
11685         int n_flag = 0;
11686         int nchars = 0;
11687         int silent = 0;
11688         struct termios tty, old_tty;
11689 #endif
11690 #if ENABLE_ASH_READ_TIMEOUT
11691         fd_set set;
11692         struct timeval ts;
11693
11694         ts.tv_sec = ts.tv_usec = 0;
11695 #endif
11696
11697         rflag = 0;
11698         prompt = NULL;
11699 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11700         while ((i = nextopt("p:rt:n:s")) != '\0')
11701 #elif ENABLE_ASH_READ_NCHARS
11702         while ((i = nextopt("p:rn:s")) != '\0')
11703 #elif ENABLE_ASH_READ_TIMEOUT
11704         while ((i = nextopt("p:rt:")) != '\0')
11705 #else
11706         while ((i = nextopt("p:r")) != '\0')
11707 #endif
11708         {
11709                 switch (i) {
11710                 case 'p':
11711                         prompt = optionarg;
11712                         break;
11713 #if ENABLE_ASH_READ_NCHARS
11714                 case 'n':
11715                         nchars = bb_strtou(optionarg, NULL, 10);
11716                         if (nchars < 0 || errno)
11717                                 ash_msg_and_raise_error("invalid count");
11718                         n_flag = nchars; /* just a flag "nchars is nonzero" */
11719                         break;
11720                 case 's':
11721                         silent = 1;
11722                         break;
11723 #endif
11724 #if ENABLE_ASH_READ_TIMEOUT
11725                 case 't':
11726                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
11727                         ts.tv_usec = 0;
11728                         /* EINVAL means number is ok, but not terminated by NUL */
11729                         if (*p == '.' && errno == EINVAL) {
11730                                 char *p2;
11731                                 if (*++p) {
11732                                         int scale;
11733                                         ts.tv_usec = bb_strtou(p, &p2, 10);
11734                                         if (errno)
11735                                                 ash_msg_and_raise_error("invalid timeout");
11736                                         scale = p2 - p;
11737                                         /* normalize to usec */
11738                                         if (scale > 6)
11739                                                 ash_msg_and_raise_error("invalid timeout");
11740                                         while (scale++ < 6)
11741                                                 ts.tv_usec *= 10;
11742                                 }
11743                         } else if (ts.tv_sec < 0 || errno) {
11744                                 ash_msg_and_raise_error("invalid timeout");
11745                         }
11746                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
11747                                 ash_msg_and_raise_error("invalid timeout");
11748                         }
11749                         break;
11750 #endif
11751                 case 'r':
11752                         rflag = 1;
11753                         break;
11754                 default:
11755                         break;
11756                 }
11757         }
11758         if (prompt && isatty(0)) {
11759                 out2str(prompt);
11760         }
11761         ap = argptr;
11762         if (*ap == NULL)
11763                 ash_msg_and_raise_error("arg count");
11764         ifs = bltinlookup("IFS");
11765         if (ifs == NULL)
11766                 ifs = defifs;
11767 #if ENABLE_ASH_READ_NCHARS
11768         if (n_flag || silent) {
11769                 if (tcgetattr(0, &tty) != 0) {
11770                         /* Not a tty */
11771                         n_flag = 0;
11772                         silent = 0;
11773                 } else {
11774                         old_tty = tty;
11775                         if (n_flag) {
11776                                 tty.c_lflag &= ~ICANON;
11777                                 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
11778                         }
11779                         if (silent) {
11780                                 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
11781                         }
11782                         tcsetattr(0, TCSANOW, &tty);
11783                 }
11784         }
11785 #endif
11786 #if ENABLE_ASH_READ_TIMEOUT
11787         if (ts.tv_sec || ts.tv_usec) {
11788                 FD_ZERO(&set);
11789                 FD_SET(0, &set);
11790
11791                 /* poll-based wait produces bigger code, using select */
11792                 i = select(1, &set, NULL, NULL, &ts);
11793                 if (!i) { /* timed out! */
11794 #if ENABLE_ASH_READ_NCHARS
11795                         if (n_flag)
11796                                 tcsetattr(0, TCSANOW, &old_tty);
11797 #endif
11798                         return 1;
11799                 }
11800         }
11801 #endif
11802         status = 0;
11803         startword = 1;
11804         backslash = 0;
11805         STARTSTACKSTR(p);
11806         do {
11807                 if (nonblock_safe_read(0, &c, 1) != 1) {
11808                         status = 1;
11809                         break;
11810                 }
11811                 if (c == '\0')
11812                         continue;
11813                 if (backslash) {
11814                         backslash = 0;
11815                         if (c != '\n')
11816                                 goto put;
11817                         continue;
11818                 }
11819                 if (!rflag && c == '\\') {
11820                         backslash++;
11821                         continue;
11822                 }
11823                 if (c == '\n')
11824                         break;
11825                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11826                         continue;
11827                 }
11828                 startword = 0;
11829                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11830                         STACKSTRNUL(p);
11831                         setvar(*ap, stackblock(), 0);
11832                         ap++;
11833                         startword = 1;
11834                         STARTSTACKSTR(p);
11835                 } else {
11836  put:
11837                         STPUTC(c, p);
11838                 }
11839         }
11840 /* end of do {} while: */
11841 #if ENABLE_ASH_READ_NCHARS
11842         while (!n_flag || --nchars);
11843 #else
11844         while (1);
11845 #endif
11846
11847 #if ENABLE_ASH_READ_NCHARS
11848         if (n_flag || silent)
11849                 tcsetattr(0, TCSANOW, &old_tty);
11850 #endif
11851
11852         STACKSTRNUL(p);
11853         /* Remove trailing blanks */
11854         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11855                 *p = '\0';
11856         setvar(*ap, stackblock(), 0);
11857         while (*++ap != NULL)
11858                 setvar(*ap, nullstr, 0);
11859         return status;
11860 }
11861
11862 static int
11863 umaskcmd(int argc, char **argv)
11864 {
11865         static const char permuser[3] ALIGN1 = "ugo";
11866         static const char permmode[3] ALIGN1 = "rwx";
11867         static const short permmask[] ALIGN2 = {
11868                 S_IRUSR, S_IWUSR, S_IXUSR,
11869                 S_IRGRP, S_IWGRP, S_IXGRP,
11870                 S_IROTH, S_IWOTH, S_IXOTH
11871         };
11872
11873         char *ap;
11874         mode_t mask;
11875         int i;
11876         int symbolic_mode = 0;
11877
11878         while (nextopt("S") != '\0') {
11879                 symbolic_mode = 1;
11880         }
11881
11882         INT_OFF;
11883         mask = umask(0);
11884         umask(mask);
11885         INT_ON;
11886
11887         ap = *argptr;
11888         if (ap == NULL) {
11889                 if (symbolic_mode) {
11890                         char buf[18];
11891                         char *p = buf;
11892
11893                         for (i = 0; i < 3; i++) {
11894                                 int j;
11895
11896                                 *p++ = permuser[i];
11897                                 *p++ = '=';
11898                                 for (j = 0; j < 3; j++) {
11899                                         if ((mask & permmask[3 * i + j]) == 0) {
11900                                                 *p++ = permmode[j];
11901                                         }
11902                                 }
11903                                 *p++ = ',';
11904                         }
11905                         *--p = 0;
11906                         puts(buf);
11907                 } else {
11908                         out1fmt("%.4o\n", mask);
11909                 }
11910         } else {
11911                 if (isdigit((unsigned char) *ap)) {
11912                         mask = 0;
11913                         do {
11914                                 if (*ap >= '8' || *ap < '0')
11915                                         ash_msg_and_raise_error(illnum, argv[1]);
11916                                 mask = (mask << 3) + (*ap - '0');
11917                         } while (*++ap != '\0');
11918                         umask(mask);
11919                 } else {
11920                         mask = ~mask & 0777;
11921                         if (!bb_parse_mode(ap, &mask)) {
11922                                 ash_msg_and_raise_error("illegal mode: %s", ap);
11923                         }
11924                         umask(~mask & 0777);
11925                 }
11926         }
11927         return 0;
11928 }
11929
11930 /*
11931  * ulimit builtin
11932  *
11933  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11934  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11935  * ash by J.T. Conklin.
11936  *
11937  * Public domain.
11938  */
11939
11940 struct limits {
11941         uint8_t cmd;          /* RLIMIT_xxx fit into it */
11942         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
11943         char    option;
11944 };
11945
11946 static const struct limits limits_tbl[] = {
11947 #ifdef RLIMIT_CPU
11948         { RLIMIT_CPU,        0, 't' },
11949 #endif
11950 #ifdef RLIMIT_FSIZE
11951         { RLIMIT_FSIZE,      9, 'f' },
11952 #endif
11953 #ifdef RLIMIT_DATA
11954         { RLIMIT_DATA,      10, 'd' },
11955 #endif
11956 #ifdef RLIMIT_STACK
11957         { RLIMIT_STACK,     10, 's' },
11958 #endif
11959 #ifdef RLIMIT_CORE
11960         { RLIMIT_CORE,       9, 'c' },
11961 #endif
11962 #ifdef RLIMIT_RSS
11963         { RLIMIT_RSS,       10, 'm' },
11964 #endif
11965 #ifdef RLIMIT_MEMLOCK
11966         { RLIMIT_MEMLOCK,   10, 'l' },
11967 #endif
11968 #ifdef RLIMIT_NPROC
11969         { RLIMIT_NPROC,      0, 'p' },
11970 #endif
11971 #ifdef RLIMIT_NOFILE
11972         { RLIMIT_NOFILE,     0, 'n' },
11973 #endif
11974 #ifdef RLIMIT_AS
11975         { RLIMIT_AS,        10, 'v' },
11976 #endif
11977 #ifdef RLIMIT_LOCKS
11978         { RLIMIT_LOCKS,      0, 'w' },
11979 #endif
11980 };
11981 static const char limits_name[] =
11982 #ifdef RLIMIT_CPU
11983         "time(seconds)" "\0"
11984 #endif
11985 #ifdef RLIMIT_FSIZE
11986         "file(blocks)" "\0"
11987 #endif
11988 #ifdef RLIMIT_DATA
11989         "data(kb)" "\0"
11990 #endif
11991 #ifdef RLIMIT_STACK
11992         "stack(kb)" "\0"
11993 #endif
11994 #ifdef RLIMIT_CORE
11995         "coredump(blocks)" "\0"
11996 #endif
11997 #ifdef RLIMIT_RSS
11998         "memory(kb)" "\0"
11999 #endif
12000 #ifdef RLIMIT_MEMLOCK
12001         "locked memory(kb)" "\0"
12002 #endif
12003 #ifdef RLIMIT_NPROC
12004         "process" "\0"
12005 #endif
12006 #ifdef RLIMIT_NOFILE
12007         "nofiles" "\0"
12008 #endif
12009 #ifdef RLIMIT_AS
12010         "vmemory(kb)" "\0"
12011 #endif
12012 #ifdef RLIMIT_LOCKS
12013         "locks" "\0"
12014 #endif
12015 ;
12016
12017 enum limtype { SOFT = 0x1, HARD = 0x2 };
12018
12019 static void
12020 printlim(enum limtype how, const struct rlimit *limit,
12021                         const struct limits *l)
12022 {
12023         rlim_t val;
12024
12025         val = limit->rlim_max;
12026         if (how & SOFT)
12027                 val = limit->rlim_cur;
12028
12029         if (val == RLIM_INFINITY)
12030                 out1fmt("unlimited\n");
12031         else {
12032                 val >>= l->factor_shift;
12033                 out1fmt("%lld\n", (long long) val);
12034         }
12035 }
12036
12037 static int
12038 ulimitcmd(int argc, char **argv)
12039 {
12040         int c;
12041         rlim_t val = 0;
12042         enum limtype how = SOFT | HARD;
12043         const struct limits *l;
12044         int set, all = 0;
12045         int optc, what;
12046         struct rlimit limit;
12047
12048         what = 'f';
12049         while ((optc = nextopt("HSa"
12050 #ifdef RLIMIT_CPU
12051                                 "t"
12052 #endif
12053 #ifdef RLIMIT_FSIZE
12054                                 "f"
12055 #endif
12056 #ifdef RLIMIT_DATA
12057                                 "d"
12058 #endif
12059 #ifdef RLIMIT_STACK
12060                                 "s"
12061 #endif
12062 #ifdef RLIMIT_CORE
12063                                 "c"
12064 #endif
12065 #ifdef RLIMIT_RSS
12066                                 "m"
12067 #endif
12068 #ifdef RLIMIT_MEMLOCK
12069                                 "l"
12070 #endif
12071 #ifdef RLIMIT_NPROC
12072                                 "p"
12073 #endif
12074 #ifdef RLIMIT_NOFILE
12075                                 "n"
12076 #endif
12077 #ifdef RLIMIT_AS
12078                                 "v"
12079 #endif
12080 #ifdef RLIMIT_LOCKS
12081                                 "w"
12082 #endif
12083                                         )) != '\0')
12084                 switch (optc) {
12085                 case 'H':
12086                         how = HARD;
12087                         break;
12088                 case 'S':
12089                         how = SOFT;
12090                         break;
12091                 case 'a':
12092                         all = 1;
12093                         break;
12094                 default:
12095                         what = optc;
12096                 }
12097
12098         for (l = limits_tbl; l->option != what; l++)
12099                 continue;
12100
12101         set = *argptr ? 1 : 0;
12102         if (set) {
12103                 char *p = *argptr;
12104
12105                 if (all || argptr[1])
12106                         ash_msg_and_raise_error("too many arguments");
12107                 if (strncmp(p, "unlimited\n", 9) == 0)
12108                         val = RLIM_INFINITY;
12109                 else {
12110                         val = (rlim_t) 0;
12111
12112                         while ((c = *p++) >= '0' && c <= '9') {
12113                                 val = (val * 10) + (long)(c - '0');
12114                                 if (val < (rlim_t) 0)
12115                                         break;
12116                         }
12117                         if (c)
12118                                 ash_msg_and_raise_error("bad number");
12119                         val <<= l->factor_shift;
12120                 }
12121         }
12122         if (all) {
12123                 const char *lname = limits_name;
12124                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12125                         getrlimit(l->cmd, &limit);
12126                         out1fmt("%-20s ", lname);
12127                         lname += strlen(lname) + 1;
12128                         printlim(how, &limit, l);
12129                 }
12130                 return 0;
12131         }
12132
12133         getrlimit(l->cmd, &limit);
12134         if (set) {
12135                 if (how & HARD)
12136                         limit.rlim_max = val;
12137                 if (how & SOFT)
12138                         limit.rlim_cur = val;
12139                 if (setrlimit(l->cmd, &limit) < 0)
12140                         ash_msg_and_raise_error("error setting limit (%m)");
12141         } else {
12142                 printlim(how, &limit, l);
12143         }
12144         return 0;
12145 }
12146
12147
12148 /* ============ Math support */
12149
12150 #if ENABLE_ASH_MATH_SUPPORT
12151
12152 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12153
12154    Permission is hereby granted, free of charge, to any person obtaining
12155    a copy of this software and associated documentation files (the
12156    "Software"), to deal in the Software without restriction, including
12157    without limitation the rights to use, copy, modify, merge, publish,
12158    distribute, sublicense, and/or sell copies of the Software, and to
12159    permit persons to whom the Software is furnished to do so, subject to
12160    the following conditions:
12161
12162    The above copyright notice and this permission notice shall be
12163    included in all copies or substantial portions of the Software.
12164
12165    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12166    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12167    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12168    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12169    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12170    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12171    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12172 */
12173
12174 /* This is my infix parser/evaluator. It is optimized for size, intended
12175  * as a replacement for yacc-based parsers. However, it may well be faster
12176  * than a comparable parser written in yacc. The supported operators are
12177  * listed in #defines below. Parens, order of operations, and error handling
12178  * are supported. This code is thread safe. The exact expression format should
12179  * be that which POSIX specifies for shells. */
12180
12181 /* The code uses a simple two-stack algorithm. See
12182  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12183  * for a detailed explanation of the infix-to-postfix algorithm on which
12184  * this is based (this code differs in that it applies operators immediately
12185  * to the stack instead of adding them to a queue to end up with an
12186  * expression). */
12187
12188 /* To use the routine, call it with an expression string and error return
12189  * pointer */
12190
12191 /*
12192  * Aug 24, 2001              Manuel Novoa III
12193  *
12194  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12195  *
12196  * 1) In arith_apply():
12197  *    a) Cached values of *numptr and &(numptr[-1]).
12198  *    b) Removed redundant test for zero denominator.
12199  *
12200  * 2) In arith():
12201  *    a) Eliminated redundant code for processing operator tokens by moving
12202  *       to a table-based implementation.  Also folded handling of parens
12203  *       into the table.
12204  *    b) Combined all 3 loops which called arith_apply to reduce generated
12205  *       code size at the cost of speed.
12206  *
12207  * 3) The following expressions were treated as valid by the original code:
12208  *       1()  ,    0!  ,    1 ( *3 )   .
12209  *    These bugs have been fixed by internally enclosing the expression in
12210  *    parens and then checking that all binary ops and right parens are
12211  *    preceded by a valid expression (NUM_TOKEN).
12212  *
12213  * Note: It may be desirable to replace Aaron's test for whitespace with
12214  * ctype's isspace() if it is used by another busybox applet or if additional
12215  * whitespace chars should be considered.  Look below the "#include"s for a
12216  * precompiler test.
12217  */
12218
12219 /*
12220  * Aug 26, 2001              Manuel Novoa III
12221  *
12222  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12223  *
12224  * Merge in Aaron's comments previously posted to the busybox list,
12225  * modified slightly to take account of my changes to the code.
12226  *
12227  */
12228
12229 /*
12230  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12231  *
12232  * - allow access to variable,
12233  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12234  * - realize assign syntax (VAR=expr, +=, *= etc)
12235  * - realize exponentiation (** operator)
12236  * - realize comma separated - expr, expr
12237  * - realise ++expr --expr expr++ expr--
12238  * - realise expr ? expr : expr (but, second expr calculate always)
12239  * - allow hexadecimal and octal numbers
12240  * - was restored loses XOR operator
12241  * - remove one goto label, added three ;-)
12242  * - protect $((num num)) as true zero expr (Manuel`s error)
12243  * - always use special isspace(), see comment from bash ;-)
12244  */
12245
12246 #define arith_isspace(arithval) \
12247         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12248
12249 typedef unsigned char operator;
12250
12251 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12252  * precedence, and 3 high bits are an ID unique across operators of that
12253  * precedence. The ID portion is so that multiple operators can have the
12254  * same precedence, ensuring that the leftmost one is evaluated first.
12255  * Consider * and /. */
12256
12257 #define tok_decl(prec,id) (((id)<<5)|(prec))
12258 #define PREC(op) ((op) & 0x1F)
12259
12260 #define TOK_LPAREN tok_decl(0,0)
12261
12262 #define TOK_COMMA tok_decl(1,0)
12263
12264 #define TOK_ASSIGN tok_decl(2,0)
12265 #define TOK_AND_ASSIGN tok_decl(2,1)
12266 #define TOK_OR_ASSIGN tok_decl(2,2)
12267 #define TOK_XOR_ASSIGN tok_decl(2,3)
12268 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12269 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12270 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12271 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12272
12273 #define TOK_MUL_ASSIGN tok_decl(3,0)
12274 #define TOK_DIV_ASSIGN tok_decl(3,1)
12275 #define TOK_REM_ASSIGN tok_decl(3,2)
12276
12277 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12278 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12279
12280 /* conditional is right associativity too */
12281 #define TOK_CONDITIONAL tok_decl(4,0)
12282 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12283
12284 #define TOK_OR tok_decl(5,0)
12285
12286 #define TOK_AND tok_decl(6,0)
12287
12288 #define TOK_BOR tok_decl(7,0)
12289
12290 #define TOK_BXOR tok_decl(8,0)
12291
12292 #define TOK_BAND tok_decl(9,0)
12293
12294 #define TOK_EQ tok_decl(10,0)
12295 #define TOK_NE tok_decl(10,1)
12296
12297 #define TOK_LT tok_decl(11,0)
12298 #define TOK_GT tok_decl(11,1)
12299 #define TOK_GE tok_decl(11,2)
12300 #define TOK_LE tok_decl(11,3)
12301
12302 #define TOK_LSHIFT tok_decl(12,0)
12303 #define TOK_RSHIFT tok_decl(12,1)
12304
12305 #define TOK_ADD tok_decl(13,0)
12306 #define TOK_SUB tok_decl(13,1)
12307
12308 #define TOK_MUL tok_decl(14,0)
12309 #define TOK_DIV tok_decl(14,1)
12310 #define TOK_REM tok_decl(14,2)
12311
12312 /* exponent is right associativity */
12313 #define TOK_EXPONENT tok_decl(15,1)
12314
12315 /* For now unary operators. */
12316 #define UNARYPREC 16
12317 #define TOK_BNOT tok_decl(UNARYPREC,0)
12318 #define TOK_NOT tok_decl(UNARYPREC,1)
12319
12320 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12321 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12322
12323 #define PREC_PRE (UNARYPREC+2)
12324
12325 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12326 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12327
12328 #define PREC_POST (UNARYPREC+3)
12329
12330 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12331 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12332
12333 #define SPEC_PREC (UNARYPREC+4)
12334
12335 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12336 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12337
12338 #define NUMPTR (*numstackptr)
12339
12340 static int
12341 tok_have_assign(operator op)
12342 {
12343         operator prec = PREC(op);
12344
12345         convert_prec_is_assing(prec);
12346         return (prec == PREC(TOK_ASSIGN) ||
12347                         prec == PREC_PRE || prec == PREC_POST);
12348 }
12349
12350 static int
12351 is_right_associativity(operator prec)
12352 {
12353         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12354                 || prec == PREC(TOK_CONDITIONAL));
12355 }
12356
12357 typedef struct ARITCH_VAR_NUM {
12358         arith_t val;
12359         arith_t contidional_second_val;
12360         char contidional_second_val_initialized;
12361         char *var;      /* if NULL then is regular number,
12362                            else is variable name */
12363 } v_n_t;
12364
12365 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12366         const char *var;
12367         struct CHK_VAR_RECURSIVE_LOOPED *next;
12368 } chk_var_recursive_looped_t;
12369
12370 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12371
12372 static int
12373 arith_lookup_val(v_n_t *t)
12374 {
12375         if (t->var) {
12376                 const char * p = lookupvar(t->var);
12377
12378                 if (p) {
12379                         int errcode;
12380
12381                         /* recursive try as expression */
12382                         chk_var_recursive_looped_t *cur;
12383                         chk_var_recursive_looped_t cur_save;
12384
12385                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12386                                 if (strcmp(cur->var, t->var) == 0) {
12387                                         /* expression recursion loop detected */
12388                                         return -5;
12389                                 }
12390                         }
12391                         /* save current lookuped var name */
12392                         cur = prev_chk_var_recursive;
12393                         cur_save.var = t->var;
12394                         cur_save.next = cur;
12395                         prev_chk_var_recursive = &cur_save;
12396
12397                         t->val = arith (p, &errcode);
12398                         /* restore previous ptr after recursiving */
12399                         prev_chk_var_recursive = cur;
12400                         return errcode;
12401                 }
12402                 /* allow undefined var as 0 */
12403                 t->val = 0;
12404         }
12405         return 0;
12406 }
12407
12408 /* "applying" a token means performing it on the top elements on the integer
12409  * stack. For a unary operator it will only change the top element, but a
12410  * binary operator will pop two arguments and push a result */
12411 static int
12412 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12413 {
12414         v_n_t *numptr_m1;
12415         arith_t numptr_val, rez;
12416         int ret_arith_lookup_val;
12417
12418         /* There is no operator that can work without arguments */
12419         if (NUMPTR == numstack) goto err;
12420         numptr_m1 = NUMPTR - 1;
12421
12422         /* check operand is var with noninteger value */
12423         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12424         if (ret_arith_lookup_val)
12425                 return ret_arith_lookup_val;
12426
12427         rez = numptr_m1->val;
12428         if (op == TOK_UMINUS)
12429                 rez *= -1;
12430         else if (op == TOK_NOT)
12431                 rez = !rez;
12432         else if (op == TOK_BNOT)
12433                 rez = ~rez;
12434         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12435                 rez++;
12436         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12437                 rez--;
12438         else if (op != TOK_UPLUS) {
12439                 /* Binary operators */
12440
12441                 /* check and binary operators need two arguments */
12442                 if (numptr_m1 == numstack) goto err;
12443
12444                 /* ... and they pop one */
12445                 --NUMPTR;
12446                 numptr_val = rez;
12447                 if (op == TOK_CONDITIONAL) {
12448                         if (! numptr_m1->contidional_second_val_initialized) {
12449                                 /* protect $((expr1 ? expr2)) without ": expr" */
12450                                 goto err;
12451                         }
12452                         rez = numptr_m1->contidional_second_val;
12453                 } else if (numptr_m1->contidional_second_val_initialized) {
12454                         /* protect $((expr1 : expr2)) without "expr ? " */
12455                         goto err;
12456                 }
12457                 numptr_m1 = NUMPTR - 1;
12458                 if (op != TOK_ASSIGN) {
12459                         /* check operand is var with noninteger value for not '=' */
12460                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12461                         if (ret_arith_lookup_val)
12462                                 return ret_arith_lookup_val;
12463                 }
12464                 if (op == TOK_CONDITIONAL) {
12465                         numptr_m1->contidional_second_val = rez;
12466                 }
12467                 rez = numptr_m1->val;
12468                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12469                         rez |= numptr_val;
12470                 else if (op == TOK_OR)
12471                         rez = numptr_val || rez;
12472                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12473                         rez &= numptr_val;
12474                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12475                         rez ^= numptr_val;
12476                 else if (op == TOK_AND)
12477                         rez = rez && numptr_val;
12478                 else if (op == TOK_EQ)
12479                         rez = (rez == numptr_val);
12480                 else if (op == TOK_NE)
12481                         rez = (rez != numptr_val);
12482                 else if (op == TOK_GE)
12483                         rez = (rez >= numptr_val);
12484                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12485                         rez >>= numptr_val;
12486                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12487                         rez <<= numptr_val;
12488                 else if (op == TOK_GT)
12489                         rez = (rez > numptr_val);
12490                 else if (op == TOK_LT)
12491                         rez = (rez < numptr_val);
12492                 else if (op == TOK_LE)
12493                         rez = (rez <= numptr_val);
12494                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12495                         rez *= numptr_val;
12496                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12497                         rez += numptr_val;
12498                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12499                         rez -= numptr_val;
12500                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12501                         rez = numptr_val;
12502                 else if (op == TOK_CONDITIONAL_SEP) {
12503                         if (numptr_m1 == numstack) {
12504                                 /* protect $((expr : expr)) without "expr ? " */
12505                                 goto err;
12506                         }
12507                         numptr_m1->contidional_second_val_initialized = op;
12508                         numptr_m1->contidional_second_val = numptr_val;
12509                 } else if (op == TOK_CONDITIONAL) {
12510                         rez = rez ?
12511                                 numptr_val : numptr_m1->contidional_second_val;
12512                 } else if (op == TOK_EXPONENT) {
12513                         if (numptr_val < 0)
12514                                 return -3;      /* exponent less than 0 */
12515                         else {
12516                                 arith_t c = 1;
12517
12518                                 if (numptr_val)
12519                                         while (numptr_val--)
12520                                                 c *= rez;
12521                                 rez = c;
12522                         }
12523                 } else if (numptr_val==0)          /* zero divisor check */
12524                         return -2;
12525                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12526                         rez /= numptr_val;
12527                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12528                         rez %= numptr_val;
12529         }
12530         if (tok_have_assign(op)) {
12531                 char buf[sizeof(arith_t_type)*3 + 2];
12532
12533                 if (numptr_m1->var == NULL) {
12534                         /* Hmm, 1=2 ? */
12535                         goto err;
12536                 }
12537                 /* save to shell variable */
12538 #if ENABLE_ASH_MATH_SUPPORT_64
12539                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12540 #else
12541                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12542 #endif
12543                 setvar(numptr_m1->var, buf, 0);
12544                 /* after saving, make previous value for v++ or v-- */
12545                 if (op == TOK_POST_INC)
12546                         rez--;
12547                 else if (op == TOK_POST_DEC)
12548                         rez++;
12549         }
12550         numptr_m1->val = rez;
12551         /* protect geting var value, is number now */
12552         numptr_m1->var = NULL;
12553         return 0;
12554  err:
12555         return -1;
12556 }
12557
12558 /* longest must be first */
12559 static const char op_tokens[] ALIGN1 = {
12560         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12561         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12562         '<','<',    0, TOK_LSHIFT,
12563         '>','>',    0, TOK_RSHIFT,
12564         '|','|',    0, TOK_OR,
12565         '&','&',    0, TOK_AND,
12566         '!','=',    0, TOK_NE,
12567         '<','=',    0, TOK_LE,
12568         '>','=',    0, TOK_GE,
12569         '=','=',    0, TOK_EQ,
12570         '|','=',    0, TOK_OR_ASSIGN,
12571         '&','=',    0, TOK_AND_ASSIGN,
12572         '*','=',    0, TOK_MUL_ASSIGN,
12573         '/','=',    0, TOK_DIV_ASSIGN,
12574         '%','=',    0, TOK_REM_ASSIGN,
12575         '+','=',    0, TOK_PLUS_ASSIGN,
12576         '-','=',    0, TOK_MINUS_ASSIGN,
12577         '-','-',    0, TOK_POST_DEC,
12578         '^','=',    0, TOK_XOR_ASSIGN,
12579         '+','+',    0, TOK_POST_INC,
12580         '*','*',    0, TOK_EXPONENT,
12581         '!',        0, TOK_NOT,
12582         '<',        0, TOK_LT,
12583         '>',        0, TOK_GT,
12584         '=',        0, TOK_ASSIGN,
12585         '|',        0, TOK_BOR,
12586         '&',        0, TOK_BAND,
12587         '*',        0, TOK_MUL,
12588         '/',        0, TOK_DIV,
12589         '%',        0, TOK_REM,
12590         '+',        0, TOK_ADD,
12591         '-',        0, TOK_SUB,
12592         '^',        0, TOK_BXOR,
12593         /* uniq */
12594         '~',        0, TOK_BNOT,
12595         ',',        0, TOK_COMMA,
12596         '?',        0, TOK_CONDITIONAL,
12597         ':',        0, TOK_CONDITIONAL_SEP,
12598         ')',        0, TOK_RPAREN,
12599         '(',        0, TOK_LPAREN,
12600         0
12601 };
12602 /* ptr to ")" */
12603 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12604
12605 static arith_t
12606 arith(const char *expr, int *perrcode)
12607 {
12608         char arithval; /* Current character under analysis */
12609         operator lasttok, op;
12610         operator prec;
12611
12612         const char *p = endexpression;
12613         int errcode;
12614
12615         size_t datasizes = strlen(expr) + 2;
12616
12617         /* Stack of integers */
12618         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12619          * in any given correct or incorrect expression is left as an exercise to
12620          * the reader. */
12621         v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12622                                 *numstackptr = numstack;
12623         /* Stack of operator tokens */
12624         operator *stack = alloca((datasizes) * sizeof(operator)),
12625                                 *stackptr = stack;
12626
12627         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
12628         *perrcode = errcode = 0;
12629
12630         while (1) {
12631                 arithval = *expr;
12632                 if (arithval == 0) {
12633                         if (p == endexpression) {
12634                                 /* Null expression. */
12635                                 return 0;
12636                         }
12637
12638                         /* This is only reached after all tokens have been extracted from the
12639                          * input stream. If there are still tokens on the operator stack, they
12640                          * are to be applied in order. At the end, there should be a final
12641                          * result on the integer stack */
12642
12643                         if (expr != endexpression + 1) {
12644                                 /* If we haven't done so already, */
12645                                 /* append a closing right paren */
12646                                 expr = endexpression;
12647                                 /* and let the loop process it. */
12648                                 continue;
12649                         }
12650                         /* At this point, we're done with the expression. */
12651                         if (numstackptr != numstack+1) {
12652                                 /* ... but if there isn't, it's bad */
12653  err:
12654                                 return (*perrcode = -1);
12655                         }
12656                         if (numstack->var) {
12657                                 /* expression is $((var)) only, lookup now */
12658                                 errcode = arith_lookup_val(numstack);
12659                         }
12660  ret:
12661                         *perrcode = errcode;
12662                         return numstack->val;
12663                 }
12664
12665                 /* Continue processing the expression. */
12666                 if (arith_isspace(arithval)) {
12667                         /* Skip whitespace */
12668                         goto prologue;
12669                 }
12670                 p = endofname(expr);
12671                 if (p != expr) {
12672                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
12673
12674                         numstackptr->var = alloca(var_name_size);
12675                         safe_strncpy(numstackptr->var, expr, var_name_size);
12676                         expr = p;
12677  num:
12678                         numstackptr->contidional_second_val_initialized = 0;
12679                         numstackptr++;
12680                         lasttok = TOK_NUM;
12681                         continue;
12682                 }
12683                 if (isdigit(arithval)) {
12684                         numstackptr->var = NULL;
12685 #if ENABLE_ASH_MATH_SUPPORT_64
12686                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
12687 #else
12688                         numstackptr->val = strtol(expr, (char **) &expr, 0);
12689 #endif
12690                         goto num;
12691                 }
12692                 for (p = op_tokens; ; p++) {
12693                         const char *o;
12694
12695                         if (*p == 0) {
12696                                 /* strange operator not found */
12697                                 goto err;
12698                         }
12699                         for (o = expr; *p && *o == *p; p++)
12700                                 o++;
12701                         if (! *p) {
12702                                 /* found */
12703                                 expr = o - 1;
12704                                 break;
12705                         }
12706                         /* skip tail uncompared token */
12707                         while (*p)
12708                                 p++;
12709                         /* skip zero delim */
12710                         p++;
12711                 }
12712                 op = p[1];
12713
12714                 /* post grammar: a++ reduce to num */
12715                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12716                         lasttok = TOK_NUM;
12717
12718                 /* Plus and minus are binary (not unary) _only_ if the last
12719                  * token was as number, or a right paren (which pretends to be
12720                  * a number, since it evaluates to one). Think about it.
12721                  * It makes sense. */
12722                 if (lasttok != TOK_NUM) {
12723                         switch (op) {
12724                         case TOK_ADD:
12725                                 op = TOK_UPLUS;
12726                                 break;
12727                         case TOK_SUB:
12728                                 op = TOK_UMINUS;
12729                                 break;
12730                         case TOK_POST_INC:
12731                                 op = TOK_PRE_INC;
12732                                 break;
12733                         case TOK_POST_DEC:
12734                                 op = TOK_PRE_DEC;
12735                                 break;
12736                         }
12737                 }
12738                 /* We don't want a unary operator to cause recursive descent on the
12739                  * stack, because there can be many in a row and it could cause an
12740                  * operator to be evaluated before its argument is pushed onto the
12741                  * integer stack. */
12742                 /* But for binary operators, "apply" everything on the operator
12743                  * stack until we find an operator with a lesser priority than the
12744                  * one we have just extracted. */
12745                 /* Left paren is given the lowest priority so it will never be
12746                  * "applied" in this way.
12747                  * if associativity is right and priority eq, applied also skip
12748                  */
12749                 prec = PREC(op);
12750                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12751                         /* not left paren or unary */
12752                         if (lasttok != TOK_NUM) {
12753                                 /* binary op must be preceded by a num */
12754                                 goto err;
12755                         }
12756                         while (stackptr != stack) {
12757                                 if (op == TOK_RPAREN) {
12758                                         /* The algorithm employed here is simple: while we don't
12759                                          * hit an open paren nor the bottom of the stack, pop
12760                                          * tokens and apply them */
12761                                         if (stackptr[-1] == TOK_LPAREN) {
12762                                                 --stackptr;
12763                                                 /* Any operator directly after a */
12764                                                 lasttok = TOK_NUM;
12765                                                 /* close paren should consider itself binary */
12766                                                 goto prologue;
12767                                         }
12768                                 } else {
12769                                         operator prev_prec = PREC(stackptr[-1]);
12770
12771                                         convert_prec_is_assing(prec);
12772                                         convert_prec_is_assing(prev_prec);
12773                                         if (prev_prec < prec)
12774                                                 break;
12775                                         /* check right assoc */
12776                                         if (prev_prec == prec && is_right_associativity(prec))
12777                                                 break;
12778                                 }
12779                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12780                                 if (errcode) goto ret;
12781                         }
12782                         if (op == TOK_RPAREN) {
12783                                 goto err;
12784                         }
12785                 }
12786
12787                 /* Push this operator to the stack and remember it. */
12788                 *stackptr++ = lasttok = op;
12789  prologue:
12790                 ++expr;
12791         } /* while */
12792 }
12793 #endif /* ASH_MATH_SUPPORT */
12794
12795
12796 /* ============ main() and helpers */
12797
12798 /*
12799  * Called to exit the shell.
12800  */
12801 static void exitshell(void) ATTRIBUTE_NORETURN;
12802 static void
12803 exitshell(void)
12804 {
12805         struct jmploc loc;
12806         char *p;
12807         int status;
12808
12809         status = exitstatus;
12810         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12811         if (setjmp(loc.loc)) {
12812                 if (exception == EXEXIT)
12813 /* dash bug: it just does _exit(exitstatus) here
12814  * but we have to do setjobctl(0) first!
12815  * (bug is still not fixed in dash-0.5.3 - if you run dash
12816  * under Midnight Commander, on exit from dash MC is backgrounded) */
12817                         status = exitstatus;
12818                 goto out;
12819         }
12820         exception_handler = &loc;
12821         p = trap[0];
12822         if (p) {
12823                 trap[0] = NULL;
12824                 evalstring(p, 0);
12825         }
12826         flush_stdout_stderr();
12827  out:
12828         setjobctl(0);
12829         _exit(status);
12830         /* NOTREACHED */
12831 }
12832
12833 static void
12834 init(void)
12835 {
12836         /* from input.c: */
12837         basepf.nextc = basepf.buf = basebuf;
12838
12839         /* from trap.c: */
12840         signal(SIGCHLD, SIG_DFL);
12841
12842         /* from var.c: */
12843         {
12844                 char **envp;
12845                 char ppid[sizeof(int)*3 + 1];
12846                 const char *p;
12847                 struct stat st1, st2;
12848
12849                 initvar();
12850                 for (envp = environ; envp && *envp; envp++) {
12851                         if (strchr(*envp, '=')) {
12852                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12853                         }
12854                 }
12855
12856                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12857                 setvar("PPID", ppid, 0);
12858
12859                 p = lookupvar("PWD");
12860                 if (p)
12861                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12862                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12863                                 p = '\0';
12864                 setpwd(p, 0);
12865         }
12866 }
12867
12868 /*
12869  * Process the shell command line arguments.
12870  */
12871 static void
12872 procargs(int argc, char **argv)
12873 {
12874         int i;
12875         const char *xminusc;
12876         char **xargv;
12877
12878         xargv = argv;
12879         arg0 = xargv[0];
12880         if (argc > 0)
12881                 xargv++;
12882         for (i = 0; i < NOPTS; i++)
12883                 optlist[i] = 2;
12884         argptr = xargv;
12885         if (options(1)) {
12886                 /* it already printed err message */
12887                 raise_exception(EXERROR);
12888         }
12889         xargv = argptr;
12890         xminusc = minusc;
12891         if (*xargv == NULL) {
12892                 if (xminusc)
12893                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12894                 sflag = 1;
12895         }
12896         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12897                 iflag = 1;
12898         if (mflag == 2)
12899                 mflag = iflag;
12900         for (i = 0; i < NOPTS; i++)
12901                 if (optlist[i] == 2)
12902                         optlist[i] = 0;
12903 #if DEBUG == 2
12904         debug = 1;
12905 #endif
12906         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12907         if (xminusc) {
12908                 minusc = *xargv++;
12909                 if (*xargv)
12910                         goto setarg0;
12911         } else if (!sflag) {
12912                 setinputfile(*xargv, 0);
12913  setarg0:
12914                 arg0 = *xargv++;
12915                 commandname = arg0;
12916         }
12917
12918         shellparam.p = xargv;
12919 #if ENABLE_ASH_GETOPTS
12920         shellparam.optind = 1;
12921         shellparam.optoff = -1;
12922 #endif
12923         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
12924         while (*xargv) {
12925                 shellparam.nparam++;
12926                 xargv++;
12927         }
12928         optschanged();
12929 }
12930
12931 /*
12932  * Read /etc/profile or .profile.
12933  */
12934 static void
12935 read_profile(const char *name)
12936 {
12937         int skip;
12938
12939         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12940                 return;
12941         skip = cmdloop(0);
12942         popfile();
12943         if (skip)
12944                 exitshell();
12945 }
12946
12947 /*
12948  * This routine is called when an error or an interrupt occurs in an
12949  * interactive shell and control is returned to the main command loop.
12950  */
12951 static void
12952 reset(void)
12953 {
12954         /* from eval.c: */
12955         evalskip = 0;
12956         loopnest = 0;
12957         /* from input.c: */
12958         parselleft = parsenleft = 0;      /* clear input buffer */
12959         popallfiles();
12960         /* from parser.c: */
12961         tokpushback = 0;
12962         checkkwd = 0;
12963         /* from redir.c: */
12964         clearredir(0);
12965 }
12966
12967 #if PROFILE
12968 static short profile_buf[16384];
12969 extern int etext();
12970 #endif
12971
12972 /*
12973  * Main routine.  We initialize things, parse the arguments, execute
12974  * profiles if we're a login shell, and then call cmdloop to execute
12975  * commands.  The setjmp call sets up the location to jump to when an
12976  * exception occurs.  When an exception occurs the variable "state"
12977  * is used to figure out how far we had gotten.
12978  */
12979 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
12980 int ash_main(int argc, char **argv)
12981 {
12982         char *shinit;
12983         volatile int state;
12984         struct jmploc jmploc;
12985         struct stackmark smark;
12986
12987         /* Initialize global data */
12988         INIT_G_misc();
12989         INIT_G_memstack();
12990         INIT_G_var();
12991 #if ENABLE_ASH_ALIAS
12992         INIT_G_alias();
12993 #endif
12994         INIT_G_cmdtable();
12995
12996 #if PROFILE
12997         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12998 #endif
12999
13000 #if ENABLE_FEATURE_EDITING
13001         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13002 #endif
13003         state = 0;
13004         if (setjmp(jmploc.loc)) {
13005                 int e;
13006                 int s;
13007
13008                 reset();
13009
13010                 e = exception;
13011                 if (e == EXERROR)
13012                         exitstatus = 2;
13013                 s = state;
13014                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13015                         exitshell();
13016
13017                 if (e == EXINT) {
13018                         outcslow('\n', stderr);
13019                 }
13020                 popstackmark(&smark);
13021                 FORCE_INT_ON; /* enable interrupts */
13022                 if (s == 1)
13023                         goto state1;
13024                 if (s == 2)
13025                         goto state2;
13026                 if (s == 3)
13027                         goto state3;
13028                 goto state4;
13029         }
13030         exception_handler = &jmploc;
13031 #if DEBUG
13032         opentrace();
13033         trace_puts("Shell args: ");
13034         trace_puts_args(argv);
13035 #endif
13036         rootpid = getpid();
13037
13038 #if ENABLE_ASH_RANDOM_SUPPORT
13039         rseed = rootpid + time(NULL);
13040 #endif
13041         init();
13042         setstackmark(&smark);
13043         procargs(argc, argv);
13044 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13045         if (iflag) {
13046                 const char *hp = lookupvar("HISTFILE");
13047
13048                 if (hp == NULL) {
13049                         hp = lookupvar("HOME");
13050                         if (hp != NULL) {
13051                                 char *defhp = concat_path_file(hp, ".ash_history");
13052                                 setvar("HISTFILE", defhp, 0);
13053                                 free(defhp);
13054                         }
13055                 }
13056         }
13057 #endif
13058         if (argv[0] && argv[0][0] == '-')
13059                 isloginsh = 1;
13060         if (isloginsh) {
13061                 state = 1;
13062                 read_profile("/etc/profile");
13063  state1:
13064                 state = 2;
13065                 read_profile(".profile");
13066         }
13067  state2:
13068         state = 3;
13069         if (
13070 #ifndef linux
13071          getuid() == geteuid() && getgid() == getegid() &&
13072 #endif
13073          iflag
13074         ) {
13075                 shinit = lookupvar("ENV");
13076                 if (shinit != NULL && *shinit != '\0') {
13077                         read_profile(shinit);
13078                 }
13079         }
13080  state3:
13081         state = 4;
13082         if (minusc)
13083                 evalstring(minusc, 0);
13084
13085         if (sflag || minusc == NULL) {
13086 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13087                 if ( iflag ) {
13088                         const char *hp = lookupvar("HISTFILE");
13089
13090                         if (hp != NULL)
13091                                 line_input_state->hist_file = hp;
13092                 }
13093 #endif
13094  state4: /* XXX ??? - why isn't this before the "if" statement */
13095                 cmdloop(1);
13096         }
13097 #if PROFILE
13098         monitor(0);
13099 #endif
13100 #ifdef GPROF
13101         {
13102                 extern void _mcleanup(void);
13103                 _mcleanup();
13104         }
13105 #endif
13106         exitshell();
13107         /* NOTREACHED */
13108 }
13109
13110 #if DEBUG
13111 const char *applet_name = "debug stuff usage";
13112 int main(int argc, char **argv)
13113 {
13114         return ash_main(argc, argv);
13115 }
13116 #endif
13117
13118
13119 /*-
13120  * Copyright (c) 1989, 1991, 1993, 1994
13121  *      The Regents of the University of California.  All rights reserved.
13122  *
13123  * This code is derived from software contributed to Berkeley by
13124  * Kenneth Almquist.
13125  *
13126  * Redistribution and use in source and binary forms, with or without
13127  * modification, are permitted provided that the following conditions
13128  * are met:
13129  * 1. Redistributions of source code must retain the above copyright
13130  *    notice, this list of conditions and the following disclaimer.
13131  * 2. Redistributions in binary form must reproduce the above copyright
13132  *    notice, this list of conditions and the following disclaimer in the
13133  *    documentation and/or other materials provided with the distribution.
13134  * 3. Neither the name of the University nor the names of its contributors
13135  *    may be used to endorse or promote products derived from this software
13136  *    without specific prior written permission.
13137  *
13138  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13139  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13140  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13141  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13142  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13143  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13144  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13145  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13146  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13147  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13148  * SUCH DAMAGE.
13149  */