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