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