hush: fix "unterminated last line loops forever" bug
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9  * was re-ported from NetBSD and debianized.
10  *
11  *
12  * This code is derived from software contributed to Berkeley by
13  * Kenneth Almquist.
14  *
15  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
16  *
17  * Original BSD copyright notice is retained at the end of this file.
18  */
19
20 /*
21  * rewrite arith.y to micro stack based cryptic algorithm by
22  * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
23  *
24  * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
25  * dynamic variables.
26  *
27  * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28  * used in busybox and size optimizations,
29  * rewrote arith (see notes to this), added locale support,
30  * rewrote dynamic variables.
31  *
32  */
33
34 /*
35  * The follow should be set to reflect the type of system you have:
36  *      JOBS -> 1 if you have Berkeley job control, 0 otherwise.
37  *      define SYSV if you are running under System V.
38  *      define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
39  *      define DEBUG=2 to compile in and turn on debugging.
40  *
41  * When debugging is on, debugging info will be written to ./trace and
42  * a quit signal will generate a core dump.
43  */
44 #define DEBUG 0
45 #define IFS_BROKEN
46 #define PROFILE 0
47 #if ENABLE_ASH_JOB_CONTROL
48 #define JOBS 1
49 #else
50 #define JOBS 0
51 #endif
52
53 #if DEBUG
54 #define _GNU_SOURCE
55 #endif
56 #include "busybox.h"
57 #include <paths.h>
58 #include <setjmp.h>
59 #include <fnmatch.h>
60 #if JOBS || ENABLE_ASH_READ_NCHARS
61 #include <termios.h>
62 #endif
63
64 #if defined(__uClinux__)
65 #error "Do not even bother, ash will not run on uClinux"
66 #endif
67
68
69 /* ============ Misc helpers */
70
71 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
72
73 /* C99 say: "char" declaration may be signed or unsigned default */
74 #define signed_char2int(sc) ((int)((signed char)sc))
75
76
77 /* ============ Shell options */
78
79 static const char *const optletters_optnames[] = {
80         "e"   "errexit",
81         "f"   "noglob",
82         "I"   "ignoreeof",
83         "i"   "interactive",
84         "m"   "monitor",
85         "n"   "noexec",
86         "s"   "stdin",
87         "x"   "xtrace",
88         "v"   "verbose",
89         "C"   "noclobber",
90         "a"   "allexport",
91         "b"   "notify",
92         "u"   "nounset",
93         "\0"  "vi",
94 #if DEBUG
95         "\0"  "nolog",
96         "\0"  "debug",
97 #endif
98 };
99
100 #define optletters(n) optletters_optnames[(n)][0]
101 #define optnames(n) (&optletters_optnames[(n)][1])
102
103 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
104
105 static char optlist[NOPTS];
106
107 #define eflag optlist[0]
108 #define fflag optlist[1]
109 #define Iflag optlist[2]
110 #define iflag optlist[3]
111 #define mflag optlist[4]
112 #define nflag optlist[5]
113 #define sflag optlist[6]
114 #define xflag optlist[7]
115 #define vflag optlist[8]
116 #define Cflag optlist[9]
117 #define aflag optlist[10]
118 #define bflag optlist[11]
119 #define uflag optlist[12]
120 #define viflag optlist[13]
121 #if DEBUG
122 #define nolog optlist[14]
123 #define debug optlist[15]
124 #endif
125
126
127 /* ============ Misc data */
128
129 #ifdef __GLIBC__
130 /* glibc sucks */
131 static int *dash_errno;
132 #undef errno
133 #define errno (*dash_errno)
134 #endif
135
136 static char nullstr[1];                /* zero length string */
137 static const char homestr[] = "HOME";
138 static const char snlfmt[] = "%s\n";
139 static const char illnum[] = "Illegal number: %s";
140
141 static char *minusc;                   /* argument to -c option */
142
143 static int isloginsh;
144 /* pid of main shell */
145 static int rootpid;
146 /* shell level: 0 for the main shell, 1 for its children, and so on */
147 static int shlvl;
148 #define rootshell (!shlvl)
149 /* trap handler commands */
150 static char *trap[NSIG];
151 /* current value of signal */
152 static char sigmode[NSIG - 1];
153 /* indicates specified signal received */
154 static char gotsig[NSIG - 1];
155 static char *arg0; /* value of $0 */
156
157
158 /* ============ Interrupts / exceptions */
159
160 /*
161  * We enclose jmp_buf in a structure so that we can declare pointers to
162  * jump locations.  The global variable handler contains the location to
163  * jump to when an exception occurs, and the global variable exception
164  * contains a code identifying the exception.  To implement nested
165  * exception handlers, the user should save the value of handler on entry
166  * to an inner scope, set handler to point to a jmploc structure for the
167  * inner scope, and restore handler on exit from the scope.
168  */
169 struct jmploc {
170         jmp_buf loc;
171 };
172 static struct jmploc *exception_handler;
173 static int exception;
174 /* exceptions */
175 #define EXINT 0         /* SIGINT received */
176 #define EXERROR 1       /* a generic error */
177 #define EXSHELLPROC 2   /* execute a shell procedure */
178 #define EXEXEC 3        /* command execution failed */
179 #define EXEXIT 4        /* exit the shell */
180 #define EXSIG 5         /* trapped signal in wait(1) */
181 static volatile int suppressint;
182 static volatile sig_atomic_t intpending;
183 /* do we generate EXSIG events */
184 static int exsig;
185 /* last pending signal */
186 static volatile sig_atomic_t pendingsig;
187
188 /*
189  * Sigmode records the current value of the signal handlers for the various
190  * modes.  A value of zero means that the current handler is not known.
191  * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
192  */
193
194 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
195 #define S_CATCH 2               /* signal is caught */
196 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
197 #define S_HARD_IGN 4            /* signal is ignored permenantly */
198 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
199
200 /*
201  * These macros allow the user to suspend the handling of interrupt signals
202  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
203  * much more efficient and portable.  (But hacking the kernel is so much
204  * more fun than worrying about efficiency and portability. :-))
205  */
206 #define INT_OFF \
207         do { \
208                 suppressint++; \
209                 xbarrier(); \
210         } while (0)
211
212 /*
213  * Called to raise an exception.  Since C doesn't include exceptions, we
214  * just do a longjmp to the exception handler.  The type of exception is
215  * stored in the global variable "exception".
216  */
217 static void raise_exception(int) ATTRIBUTE_NORETURN;
218 static void
219 raise_exception(int e)
220 {
221 #if DEBUG
222         if (exception_handler == NULL)
223                 abort();
224 #endif
225         INT_OFF;
226         exception = e;
227         longjmp(exception_handler->loc, 1);
228 }
229
230 /*
231  * Called from trap.c when a SIGINT is received.  (If the user specifies
232  * that SIGINT is to be trapped or ignored using the trap builtin, then
233  * this routine is not called.)  Suppressint is nonzero when interrupts
234  * are held using the INT_OFF macro.  (The test for iflag is just
235  * defensive programming.)
236  */
237 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
238 static void
239 raise_interrupt(void)
240 {
241         int i;
242         sigset_t mask;
243
244         intpending = 0;
245         /* Signal is not automatically re-enabled after it is raised,
246          * do it ourself */
247         sigemptyset(&mask);
248         sigprocmask(SIG_SETMASK, &mask, 0);
249         /* pendingsig = 0; - now done in onsig() */
250
251         i = EXSIG;
252         if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
253                 if (!(rootshell && iflag)) {
254                         signal(SIGINT, SIG_DFL);
255                         raise(SIGINT);
256                 }
257                 i = EXINT;
258         }
259         raise_exception(i);
260         /* NOTREACHED */
261 }
262
263 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
264 static void
265 int_on(void)
266 {
267         if (--suppressint == 0 && intpending) {
268                 raise_interrupt();
269         }
270 }
271 #define INT_ON int_on()
272 static void
273 force_int_on(void)
274 {
275         suppressint = 0;
276         if (intpending)
277                 raise_interrupt();
278 }
279 #define FORCE_INT_ON force_int_on()
280 #else
281 #define INT_ON \
282         do { \
283                 xbarrier(); \
284                 if (--suppressint == 0 && intpending) \
285                         raise_interrupt(); \
286         } while (0)
287 #define FORCE_INT_ON \
288         do { \
289                 xbarrier(); \
290                 suppressint = 0; \
291                 if (intpending) \
292                         raise_interrupt(); \
293         } while (0)
294 #endif /* ASH_OPTIMIZE_FOR_SIZE */
295
296 #define SAVE_INT(v) ((v) = suppressint)
297
298 #define RESTORE_INT(v) \
299         do { \
300                 xbarrier(); \
301                 suppressint = (v); \
302                 if (suppressint == 0 && intpending) \
303                         raise_interrupt(); \
304         } while (0)
305
306 #define EXSIGON \
307         do { \
308                 exsig++; \
309                 xbarrier(); \
310                 if (pendingsig) \
311                         raise_exception(EXSIG); \
312         } while (0)
313 /* EXSIG is turned off by evalbltin(). */
314
315 /*
316  * Ignore a signal. Only one usage site - in forkchild()
317  */
318 static void
319 ignoresig(int signo)
320 {
321         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
322                 signal(signo, SIG_IGN);
323         }
324         sigmode[signo - 1] = S_HARD_IGN;
325 }
326
327 /*
328  * Signal handler. Only one usage site - in setsignal()
329  */
330 static void
331 onsig(int signo)
332 {
333         gotsig[signo - 1] = 1;
334         pendingsig = signo;
335
336         if (exsig || (signo == SIGINT && !trap[SIGINT])) {
337                 if (!suppressint) {
338                         pendingsig = 0;
339                         raise_interrupt();
340                 }
341                 intpending = 1;
342         }
343 }
344
345
346 /* ============ Stdout/stderr output */
347
348 static void
349 outstr(const char *p, FILE *file)
350 {
351         INT_OFF;
352         fputs(p, file);
353         INT_ON;
354 }
355
356 static void
357 flush_stdout_stderr(void)
358 {
359         INT_OFF;
360         fflush(stdout);
361         fflush(stderr);
362         INT_ON;
363 }
364
365 static void
366 flush_stderr(void)
367 {
368         INT_OFF;
369         fflush(stderr);
370         INT_ON;
371 }
372
373 static void
374 outcslow(int c, FILE *dest)
375 {
376         INT_OFF;
377         putc(c, dest);
378         fflush(dest);
379         INT_ON;
380 }
381
382 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
383 static int
384 out1fmt(const char *fmt, ...)
385 {
386         va_list ap;
387         int r;
388
389         INT_OFF;
390         va_start(ap, fmt);
391         r = vprintf(fmt, ap);
392         va_end(ap);
393         INT_ON;
394         return r;
395 }
396
397 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
398 static int
399 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
400 {
401         va_list ap;
402         int ret;
403
404         va_start(ap, fmt);
405         INT_OFF;
406         ret = vsnprintf(outbuf, length, fmt, ap);
407         va_end(ap);
408         INT_ON;
409         return ret;
410 }
411
412 static void
413 out1str(const char *p)
414 {
415         outstr(p, stdout);
416 }
417
418 static void
419 out2str(const char *p)
420 {
421         outstr(p, stderr);
422         flush_stderr();
423 }
424
425
426 /* ============ Parser structures */
427
428 /* control characters in argument strings */
429 #define CTLESC '\201'           /* escape next character */
430 #define CTLVAR '\202'           /* variable defn */
431 #define CTLENDVAR '\203'
432 #define CTLBACKQ '\204'
433 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
434 /*      CTLBACKQ | CTLQUOTE == '\205' */
435 #define CTLARI  '\206'          /* arithmetic expression */
436 #define CTLENDARI '\207'
437 #define CTLQUOTEMARK '\210'
438
439 /* variable substitution byte (follows CTLVAR) */
440 #define VSTYPE  0x0f            /* type of variable substitution */
441 #define VSNUL   0x10            /* colon--treat the empty string as unset */
442 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
443
444 /* values of VSTYPE field */
445 #define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
446 #define VSMINUS         0x2             /* ${var-text} */
447 #define VSPLUS          0x3             /* ${var+text} */
448 #define VSQUESTION      0x4             /* ${var?message} */
449 #define VSASSIGN        0x5             /* ${var=text} */
450 #define VSTRIMRIGHT     0x6             /* ${var%pattern} */
451 #define VSTRIMRIGHTMAX  0x7             /* ${var%%pattern} */
452 #define VSTRIMLEFT      0x8             /* ${var#pattern} */
453 #define VSTRIMLEFTMAX   0x9             /* ${var##pattern} */
454 #define VSLENGTH        0xa             /* ${#var} */
455
456 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
457
458 #define NCMD 0
459 #define NPIPE 1
460 #define NREDIR 2
461 #define NBACKGND 3
462 #define NSUBSHELL 4
463 #define NAND 5
464 #define NOR 6
465 #define NSEMI 7
466 #define NIF 8
467 #define NWHILE 9
468 #define NUNTIL 10
469 #define NFOR 11
470 #define NCASE 12
471 #define NCLIST 13
472 #define NDEFUN 14
473 #define NARG 15
474 #define NTO 16
475 #define NCLOBBER 17
476 #define NFROM 18
477 #define NFROMTO 19
478 #define NAPPEND 20
479 #define NTOFD 21
480 #define NFROMFD 22
481 #define NHERE 23
482 #define NXHERE 24
483 #define NNOT 25
484
485 union node;
486
487 struct ncmd {
488         int type;
489         union node *assign;
490         union node *args;
491         union node *redirect;
492 };
493
494 struct npipe {
495         int type;
496         int backgnd;
497         struct nodelist *cmdlist;
498 };
499
500 struct nredir {
501         int type;
502         union node *n;
503         union node *redirect;
504 };
505
506 struct nbinary {
507         int type;
508         union node *ch1;
509         union node *ch2;
510 };
511
512 struct nif {
513         int type;
514         union node *test;
515         union node *ifpart;
516         union node *elsepart;
517 };
518
519 struct nfor {
520         int type;
521         union node *args;
522         union node *body;
523         char *var;
524 };
525
526 struct ncase {
527         int type;
528         union node *expr;
529         union node *cases;
530 };
531
532 struct nclist {
533         int type;
534         union node *next;
535         union node *pattern;
536         union node *body;
537 };
538
539 struct narg {
540         int type;
541         union node *next;
542         char *text;
543         struct nodelist *backquote;
544 };
545
546 struct nfile {
547         int type;
548         union node *next;
549         int fd;
550         union node *fname;
551         char *expfname;
552 };
553
554 struct ndup {
555         int type;
556         union node *next;
557         int fd;
558         int dupfd;
559         union node *vname;
560 };
561
562 struct nhere {
563         int type;
564         union node *next;
565         int fd;
566         union node *doc;
567 };
568
569 struct nnot {
570         int type;
571         union node *com;
572 };
573
574 union node {
575         int type;
576         struct ncmd ncmd;
577         struct npipe npipe;
578         struct nredir nredir;
579         struct nbinary nbinary;
580         struct nif nif;
581         struct nfor nfor;
582         struct ncase ncase;
583         struct nclist nclist;
584         struct narg narg;
585         struct nfile nfile;
586         struct ndup ndup;
587         struct nhere nhere;
588         struct nnot nnot;
589 };
590
591 struct nodelist {
592         struct nodelist *next;
593         union node *n;
594 };
595
596 struct funcnode {
597         int count;
598         union node n;
599 };
600
601 /*
602  * Free a parse tree.
603  */
604 static void
605 freefunc(struct funcnode *f)
606 {
607         if (f && --f->count < 0)
608                 free(f);
609 }
610
611
612 /* ============ Debugging output */
613
614 #if DEBUG
615
616 static FILE *tracefile;
617
618 static void
619 trace_printf(const char *fmt, ...)
620 {
621         va_list va;
622
623         if (debug != 1)
624                 return;
625         va_start(va, fmt);
626         vfprintf(tracefile, fmt, va);
627         va_end(va);
628 }
629
630 static void
631 trace_vprintf(const char *fmt, va_list va)
632 {
633         if (debug != 1)
634                 return;
635         vfprintf(tracefile, fmt, va);
636 }
637
638 static void
639 trace_puts(const char *s)
640 {
641         if (debug != 1)
642                 return;
643         fputs(s, tracefile);
644 }
645
646 static void
647 trace_puts_quoted(char *s)
648 {
649         char *p;
650         char c;
651
652         if (debug != 1)
653                 return;
654         putc('"', tracefile);
655         for (p = s; *p; p++) {
656                 switch (*p) {
657                 case '\n':  c = 'n';  goto backslash;
658                 case '\t':  c = 't';  goto backslash;
659                 case '\r':  c = 'r';  goto backslash;
660                 case '"':  c = '"';  goto backslash;
661                 case '\\':  c = '\\';  goto backslash;
662                 case CTLESC:  c = 'e';  goto backslash;
663                 case CTLVAR:  c = 'v';  goto backslash;
664                 case CTLVAR+CTLQUOTE:  c = 'V'; goto backslash;
665                 case CTLBACKQ:  c = 'q';  goto backslash;
666                 case CTLBACKQ+CTLQUOTE:  c = 'Q'; goto backslash;
667  backslash:
668                         putc('\\', tracefile);
669                         putc(c, tracefile);
670                         break;
671                 default:
672                         if (*p >= ' ' && *p <= '~')
673                                 putc(*p, tracefile);
674                         else {
675                                 putc('\\', tracefile);
676                                 putc(*p >> 6 & 03, tracefile);
677                                 putc(*p >> 3 & 07, tracefile);
678                                 putc(*p & 07, tracefile);
679                         }
680                         break;
681                 }
682         }
683         putc('"', tracefile);
684 }
685
686 static void
687 trace_puts_args(char **ap)
688 {
689         if (debug != 1)
690                 return;
691         if (!*ap)
692                 return;
693         while (1) {
694                 trace_puts_quoted(*ap);
695                 if (!*++ap) {
696                         putc('\n', tracefile);
697                         break;
698                 }
699                 putc(' ', tracefile);
700         }
701 }
702
703 static void
704 opentrace(void)
705 {
706         char s[100];
707 #ifdef O_APPEND
708         int flags;
709 #endif
710
711         if (debug != 1) {
712                 if (tracefile)
713                         fflush(tracefile);
714                 /* leave open because libedit might be using it */
715                 return;
716         }
717         strcpy(s, "./trace");
718         if (tracefile) {
719                 if (!freopen(s, "a", tracefile)) {
720                         fprintf(stderr, "Can't re-open %s\n", s);
721                         debug = 0;
722                         return;
723                 }
724         } else {
725                 tracefile = fopen(s, "a");
726                 if (tracefile == NULL) {
727                         fprintf(stderr, "Can't open %s\n", s);
728                         debug = 0;
729                         return;
730                 }
731         }
732 #ifdef O_APPEND
733         flags = fcntl(fileno(tracefile), F_GETFL, 0);
734         if (flags >= 0)
735                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
736 #endif
737         setlinebuf(tracefile);
738         fputs("\nTracing started.\n", tracefile);
739 }
740
741 static void
742 indent(int amount, char *pfx, FILE *fp)
743 {
744         int i;
745
746         for (i = 0; i < amount; i++) {
747                 if (pfx && i == amount - 1)
748                         fputs(pfx, fp);
749                 putc('\t', fp);
750         }
751 }
752
753 /* little circular references here... */
754 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
755
756 static void
757 sharg(union node *arg, FILE *fp)
758 {
759         char *p;
760         struct nodelist *bqlist;
761         int subtype;
762
763         if (arg->type != NARG) {
764                 out1fmt("<node type %d>\n", arg->type);
765                 abort();
766         }
767         bqlist = arg->narg.backquote;
768         for (p = arg->narg.text; *p; p++) {
769                 switch (*p) {
770                 case CTLESC:
771                         putc(*++p, fp);
772                         break;
773                 case CTLVAR:
774                         putc('$', fp);
775                         putc('{', fp);
776                         subtype = *++p;
777                         if (subtype == VSLENGTH)
778                                 putc('#', fp);
779
780                         while (*p != '=')
781                                 putc(*p++, fp);
782
783                         if (subtype & VSNUL)
784                                 putc(':', fp);
785
786                         switch (subtype & VSTYPE) {
787                         case VSNORMAL:
788                                 putc('}', fp);
789                                 break;
790                         case VSMINUS:
791                                 putc('-', fp);
792                                 break;
793                         case VSPLUS:
794                                 putc('+', fp);
795                                 break;
796                         case VSQUESTION:
797                                 putc('?', fp);
798                                 break;
799                         case VSASSIGN:
800                                 putc('=', fp);
801                                 break;
802                         case VSTRIMLEFT:
803                                 putc('#', fp);
804                                 break;
805                         case VSTRIMLEFTMAX:
806                                 putc('#', fp);
807                                 putc('#', fp);
808                                 break;
809                         case VSTRIMRIGHT:
810                                 putc('%', fp);
811                                 break;
812                         case VSTRIMRIGHTMAX:
813                                 putc('%', fp);
814                                 putc('%', fp);
815                                 break;
816                         case VSLENGTH:
817                                 break;
818                         default:
819                                 out1fmt("<subtype %d>", subtype);
820                         }
821                         break;
822                 case CTLENDVAR:
823                         putc('}', fp);
824                         break;
825                 case CTLBACKQ:
826                 case CTLBACKQ|CTLQUOTE:
827                         putc('$', fp);
828                         putc('(', fp);
829                         shtree(bqlist->n, -1, NULL, fp);
830                         putc(')', fp);
831                         break;
832                 default:
833                         putc(*p, fp);
834                         break;
835                 }
836         }
837 }
838
839 static void
840 shcmd(union node *cmd, FILE *fp)
841 {
842         union node *np;
843         int first;
844         const char *s;
845         int dftfd;
846
847         first = 1;
848         for (np = cmd->ncmd.args; np; np = np->narg.next) {
849                 if (! first)
850                         putchar(' ');
851                 sharg(np, fp);
852                 first = 0;
853         }
854         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
855                 if (! first)
856                         putchar(' ');
857                 switch (np->nfile.type) {
858                 case NTO:       s = ">";  dftfd = 1; break;
859                 case NCLOBBER:  s = ">|"; dftfd = 1; break;
860                 case NAPPEND:   s = ">>"; dftfd = 1; break;
861                 case NTOFD:     s = ">&"; dftfd = 1; break;
862                 case NFROM:     s = "<";  dftfd = 0; break;
863                 case NFROMFD:   s = "<&"; dftfd = 0; break;
864                 case NFROMTO:   s = "<>"; dftfd = 0; break;
865                 default:        s = "*error*"; dftfd = 0; break;
866                 }
867                 if (np->nfile.fd != dftfd)
868                         fprintf(fp, "%d", np->nfile.fd);
869                 fputs(s, fp);
870                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
871                         fprintf(fp, "%d", np->ndup.dupfd);
872                 } else {
873                         sharg(np->nfile.fname, fp);
874                 }
875                 first = 0;
876         }
877 }
878
879 static void
880 shtree(union node *n, int ind, char *pfx, FILE *fp)
881 {
882         struct nodelist *lp;
883         const char *s;
884
885         if (n == NULL)
886                 return;
887
888         indent(ind, pfx, fp);
889         switch (n->type) {
890         case NSEMI:
891                 s = "; ";
892                 goto binop;
893         case NAND:
894                 s = " && ";
895                 goto binop;
896         case NOR:
897                 s = " || ";
898  binop:
899                 shtree(n->nbinary.ch1, ind, NULL, fp);
900                 /* if (ind < 0) */
901                         fputs(s, fp);
902                 shtree(n->nbinary.ch2, ind, NULL, fp);
903                 break;
904         case NCMD:
905                 shcmd(n, fp);
906                 if (ind >= 0)
907                         putc('\n', fp);
908                 break;
909         case NPIPE:
910                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
911                         shcmd(lp->n, fp);
912                         if (lp->next)
913                                 fputs(" | ", fp);
914                 }
915                 if (n->npipe.backgnd)
916                         fputs(" &", fp);
917                 if (ind >= 0)
918                         putc('\n', fp);
919                 break;
920         default:
921                 fprintf(fp, "<node type %d>", n->type);
922                 if (ind >= 0)
923                         putc('\n', fp);
924                 break;
925         }
926 }
927
928 static void
929 showtree(union node *n)
930 {
931         trace_puts("showtree called\n");
932         shtree(n, 1, NULL, stdout);
933 }
934
935 #define TRACE(param)    trace_printf param
936 #define TRACEV(param)   trace_vprintf param
937
938 #else
939
940 #define TRACE(param)
941 #define TRACEV(param)
942
943 #endif /* DEBUG */
944
945
946 /* ============ Parser data */
947
948 /*
949  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
950  */
951 struct strlist {
952         struct strlist *next;
953         char *text;
954 };
955
956 #if ENABLE_ASH_ALIAS
957 struct alias;
958 #endif
959
960 struct strpush {
961         struct strpush *prev;   /* preceding string on stack */
962         char *prevstring;
963         int prevnleft;
964 #if ENABLE_ASH_ALIAS
965         struct alias *ap;       /* if push was associated with an alias */
966 #endif
967         char *string;           /* remember the string since it may change */
968 };
969
970 struct parsefile {
971         struct parsefile *prev; /* preceding file on stack */
972         int linno;              /* current line */
973         int fd;                 /* file descriptor (or -1 if string) */
974         int nleft;              /* number of chars left in this line */
975         int lleft;              /* number of chars left in this buffer */
976         char *nextc;            /* next char in buffer */
977         char *buf;              /* input buffer */
978         struct strpush *strpush; /* for pushing strings at this level */
979         struct strpush basestrpush; /* so pushing one is fast */
980 };
981
982 static struct parsefile basepf;         /* top level input file */
983 static struct parsefile *parsefile = &basepf;  /* current input file */
984 static int startlinno;                 /* line # where last token started */
985 static char *commandname;              /* currently executing command */
986 static struct strlist *cmdenviron;     /* environment for builtin command */
987 static int exitstatus;                 /* exit status of last command */
988
989
990 /* ============ Message printing */
991
992 static void
993 ash_vmsg(const char *msg, va_list ap)
994 {
995         fprintf(stderr, "%s: ", arg0);
996         if (commandname) {
997                 if (strcmp(arg0, commandname))
998                         fprintf(stderr, "%s: ", commandname);
999                 if (!iflag || parsefile->fd)
1000                         fprintf(stderr, "line %d: ", startlinno);
1001         }
1002         vfprintf(stderr, msg, ap);
1003         outcslow('\n', stderr);
1004 }
1005
1006 /*
1007  * Exverror is called to raise the error exception.  If the second argument
1008  * is not NULL then error prints an error message using printf style
1009  * formatting.  It then raises the error exception.
1010  */
1011 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1012 static void
1013 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1014 {
1015 #if DEBUG
1016         if (msg) {
1017                 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1018                 TRACEV((msg, ap));
1019                 TRACE(("\") pid=%d\n", getpid()));
1020         } else
1021                 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1022         if (msg)
1023 #endif
1024                 ash_vmsg(msg, ap);
1025
1026         flush_stdout_stderr();
1027         raise_exception(cond);
1028         /* NOTREACHED */
1029 }
1030
1031 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1032 static void
1033 ash_msg_and_raise_error(const char *msg, ...)
1034 {
1035         va_list ap;
1036
1037         va_start(ap, msg);
1038         ash_vmsg_and_raise(EXERROR, msg, ap);
1039         /* NOTREACHED */
1040         va_end(ap);
1041 }
1042
1043 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1044 static void
1045 ash_msg_and_raise(int cond, const char *msg, ...)
1046 {
1047         va_list ap;
1048
1049         va_start(ap, msg);
1050         ash_vmsg_and_raise(cond, msg, ap);
1051         /* NOTREACHED */
1052         va_end(ap);
1053 }
1054
1055 /*
1056  * error/warning routines for external builtins
1057  */
1058 static void
1059 ash_msg(const char *fmt, ...)
1060 {
1061         va_list ap;
1062
1063         va_start(ap, fmt);
1064         ash_vmsg(fmt, ap);
1065         va_end(ap);
1066 }
1067
1068 /*
1069  * Return a string describing an error.  The returned string may be a
1070  * pointer to a static buffer that will be overwritten on the next call.
1071  * Action describes the operation that got the error.
1072  */
1073 static const char *
1074 errmsg(int e, const char *em)
1075 {
1076         if (e == ENOENT || e == ENOTDIR) {
1077                 return em;
1078         }
1079         return strerror(e);
1080 }
1081
1082
1083 /* ============ Memory allocation */
1084
1085 /*
1086  * It appears that grabstackstr() will barf with such alignments
1087  * because stalloc() will return a string allocated in a new stackblock.
1088  */
1089 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1090 enum {
1091         /* Most machines require the value returned from malloc to be aligned
1092          * in some way.  The following macro will get this right
1093          * on many machines.  */
1094         SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1095         /* Minimum size of a block */
1096         MINSIZE  = SHELL_ALIGN(504),
1097 };
1098
1099 struct stack_block {
1100         struct stack_block *prev;
1101         char space[MINSIZE];
1102 };
1103
1104 struct stackmark {
1105         struct stack_block *stackp;
1106         char *stacknxt;
1107         size_t stacknleft;
1108         struct stackmark *marknext;
1109 };
1110
1111 static struct stack_block stackbase;
1112 static struct stack_block *stackp = &stackbase;
1113 static struct stackmark *markp;
1114 static char *stacknxt = stackbase.space;
1115 static size_t stacknleft = MINSIZE;
1116 static char *sstrend = stackbase.space + MINSIZE;
1117 static int herefd = -1;
1118
1119 #define stackblock() ((void *)stacknxt)
1120 #define stackblocksize() stacknleft
1121
1122 static void *
1123 ckrealloc(void * p, size_t nbytes)
1124 {
1125         p = realloc(p, nbytes);
1126         if (!p)
1127                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1128         return p;
1129 }
1130
1131 static void *
1132 ckmalloc(size_t nbytes)
1133 {
1134         return ckrealloc(NULL, nbytes);
1135 }
1136
1137 /*
1138  * Make a copy of a string in safe storage.
1139  */
1140 static char *
1141 ckstrdup(const char *s)
1142 {
1143         char *p = strdup(s);
1144         if (!p)
1145                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1146         return p;
1147 }
1148
1149 /*
1150  * Parse trees for commands are allocated in lifo order, so we use a stack
1151  * to make this more efficient, and also to avoid all sorts of exception
1152  * handling code to handle interrupts in the middle of a parse.
1153  *
1154  * The size 504 was chosen because the Ultrix malloc handles that size
1155  * well.
1156  */
1157 static void *
1158 stalloc(size_t nbytes)
1159 {
1160         char *p;
1161         size_t aligned;
1162
1163         aligned = SHELL_ALIGN(nbytes);
1164         if (aligned > stacknleft) {
1165                 size_t len;
1166                 size_t blocksize;
1167                 struct stack_block *sp;
1168
1169                 blocksize = aligned;
1170                 if (blocksize < MINSIZE)
1171                         blocksize = MINSIZE;
1172                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1173                 if (len < blocksize)
1174                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1175                 INT_OFF;
1176                 sp = ckmalloc(len);
1177                 sp->prev = stackp;
1178                 stacknxt = sp->space;
1179                 stacknleft = blocksize;
1180                 sstrend = stacknxt + blocksize;
1181                 stackp = sp;
1182                 INT_ON;
1183         }
1184         p = stacknxt;
1185         stacknxt += aligned;
1186         stacknleft -= aligned;
1187         return p;
1188 }
1189
1190 static void
1191 stunalloc(void *p)
1192 {
1193 #if DEBUG
1194         if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1195                 write(2, "stunalloc\n", 10);
1196                 abort();
1197         }
1198 #endif
1199         stacknleft += stacknxt - (char *)p;
1200         stacknxt = p;
1201 }
1202
1203 /*
1204  * Like strdup but works with the ash stack.
1205  */
1206 static char *
1207 ststrdup(const char *p)
1208 {
1209         size_t len = strlen(p) + 1;
1210         return memcpy(stalloc(len), p, len);
1211 }
1212
1213 static void
1214 setstackmark(struct stackmark *mark)
1215 {
1216         mark->stackp = stackp;
1217         mark->stacknxt = stacknxt;
1218         mark->stacknleft = stacknleft;
1219         mark->marknext = markp;
1220         markp = mark;
1221 }
1222
1223 static void
1224 popstackmark(struct stackmark *mark)
1225 {
1226         struct stack_block *sp;
1227
1228         if (!mark->stackp)
1229                 return;
1230
1231         INT_OFF;
1232         markp = mark->marknext;
1233         while (stackp != mark->stackp) {
1234                 sp = stackp;
1235                 stackp = sp->prev;
1236                 free(sp);
1237         }
1238         stacknxt = mark->stacknxt;
1239         stacknleft = mark->stacknleft;
1240         sstrend = mark->stacknxt + mark->stacknleft;
1241         INT_ON;
1242 }
1243
1244 /*
1245  * When the parser reads in a string, it wants to stick the string on the
1246  * stack and only adjust the stack pointer when it knows how big the
1247  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1248  * of space on top of the stack and stackblocklen returns the length of
1249  * this block.  Growstackblock will grow this space by at least one byte,
1250  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1251  * part of the block that has been used.
1252  */
1253 static void
1254 growstackblock(void)
1255 {
1256         size_t newlen;
1257
1258         newlen = stacknleft * 2;
1259         if (newlen < stacknleft)
1260                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1261         if (newlen < 128)
1262                 newlen += 128;
1263
1264         if (stacknxt == stackp->space && stackp != &stackbase) {
1265                 struct stack_block *oldstackp;
1266                 struct stackmark *xmark;
1267                 struct stack_block *sp;
1268                 struct stack_block *prevstackp;
1269                 size_t grosslen;
1270
1271                 INT_OFF;
1272                 oldstackp = stackp;
1273                 sp = stackp;
1274                 prevstackp = sp->prev;
1275                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1276                 sp = ckrealloc(sp, grosslen);
1277                 sp->prev = prevstackp;
1278                 stackp = sp;
1279                 stacknxt = sp->space;
1280                 stacknleft = newlen;
1281                 sstrend = sp->space + newlen;
1282
1283                 /*
1284                  * Stack marks pointing to the start of the old block
1285                  * must be relocated to point to the new block
1286                  */
1287                 xmark = markp;
1288                 while (xmark != NULL && xmark->stackp == oldstackp) {
1289                         xmark->stackp = stackp;
1290                         xmark->stacknxt = stacknxt;
1291                         xmark->stacknleft = stacknleft;
1292                         xmark = xmark->marknext;
1293                 }
1294                 INT_ON;
1295         } else {
1296                 char *oldspace = stacknxt;
1297                 int oldlen = stacknleft;
1298                 char *p = stalloc(newlen);
1299
1300                 /* free the space we just allocated */
1301                 stacknxt = memcpy(p, oldspace, oldlen);
1302                 stacknleft += newlen;
1303         }
1304 }
1305
1306 static void
1307 grabstackblock(size_t len)
1308 {
1309         len = SHELL_ALIGN(len);
1310         stacknxt += len;
1311         stacknleft -= len;
1312 }
1313
1314 /*
1315  * The following routines are somewhat easier to use than the above.
1316  * The user declares a variable of type STACKSTR, which may be declared
1317  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1318  * the user uses the macro STPUTC to add characters to the string.  In
1319  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1320  * grown as necessary.  When the user is done, she can just leave the
1321  * string there and refer to it using stackblock().  Or she can allocate
1322  * the space for it using grabstackstr().  If it is necessary to allow
1323  * someone else to use the stack temporarily and then continue to grow
1324  * the string, the user should use grabstack to allocate the space, and
1325  * then call ungrabstr(p) to return to the previous mode of operation.
1326  *
1327  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1328  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1329  * is space for at least one character.
1330  */
1331 static void *
1332 growstackstr(void)
1333 {
1334         size_t len = stackblocksize();
1335         if (herefd >= 0 && len >= 1024) {
1336                 full_write(herefd, stackblock(), len);
1337                 return stackblock();
1338         }
1339         growstackblock();
1340         return stackblock() + len;
1341 }
1342
1343 /*
1344  * Called from CHECKSTRSPACE.
1345  */
1346 static char *
1347 makestrspace(size_t newlen, char *p)
1348 {
1349         size_t len = p - stacknxt;
1350         size_t size = stackblocksize();
1351
1352         for (;;) {
1353                 size_t nleft;
1354
1355                 size = stackblocksize();
1356                 nleft = size - len;
1357                 if (nleft >= newlen)
1358                         break;
1359                 growstackblock();
1360         }
1361         return stackblock() + len;
1362 }
1363
1364 static char *
1365 stack_nputstr(const char *s, size_t n, char *p)
1366 {
1367         p = makestrspace(n, p);
1368         p = memcpy(p, s, n) + n;
1369         return p;
1370 }
1371
1372 static char *
1373 stack_putstr(const char *s, char *p)
1374 {
1375         return stack_nputstr(s, strlen(s), p);
1376 }
1377
1378 static char *
1379 _STPUTC(int c, char *p)
1380 {
1381         if (p == sstrend)
1382                 p = growstackstr();
1383         *p++ = c;
1384         return p;
1385 }
1386
1387 #define STARTSTACKSTR(p)        ((p) = stackblock())
1388 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1389 #define CHECKSTRSPACE(n, p) \
1390         do { \
1391                 char *q = (p); \
1392                 size_t l = (n); \
1393                 size_t m = sstrend - q; \
1394                 if (l > m) \
1395                         (p) = makestrspace(l, q); \
1396         } while (0)
1397 #define USTPUTC(c, p)           (*p++ = (c))
1398 #define STACKSTRNUL(p) \
1399         do { \
1400                 if ((p) == sstrend) \
1401                         p = growstackstr(); \
1402                 *p = '\0'; \
1403         } while (0)
1404 #define STUNPUTC(p)             (--p)
1405 #define STTOPC(p)               (p[-1])
1406 #define STADJUST(amount, p)     (p += (amount))
1407
1408 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1409 #define ungrabstackstr(s, p)    stunalloc((s))
1410 #define stackstrend()           ((void *)sstrend)
1411
1412
1413 /* ============ String helpers */
1414
1415 /*
1416  * prefix -- see if pfx is a prefix of string.
1417  */
1418 static char *
1419 prefix(const char *string, const char *pfx)
1420 {
1421         while (*pfx) {
1422                 if (*pfx++ != *string++)
1423                         return 0;
1424         }
1425         return (char *) string;
1426 }
1427
1428 /*
1429  * Check for a valid number.  This should be elsewhere.
1430  */
1431 static int
1432 is_number(const char *p)
1433 {
1434         do {
1435                 if (!isdigit(*p))
1436                         return 0;
1437         } while (*++p != '\0');
1438         return 1;
1439 }
1440
1441 /*
1442  * Convert a string of digits to an integer, printing an error message on
1443  * failure.
1444  */
1445 static int
1446 number(const char *s)
1447 {
1448         if (!is_number(s))
1449                 ash_msg_and_raise_error(illnum, s);
1450         return atoi(s);
1451 }
1452
1453 /*
1454  * Produce a possibly single quoted string suitable as input to the shell.
1455  * The return string is allocated on the stack.
1456  */
1457 static char *
1458 single_quote(const char *s)
1459 {
1460         char *p;
1461
1462         STARTSTACKSTR(p);
1463
1464         do {
1465                 char *q;
1466                 size_t len;
1467
1468                 len = strchrnul(s, '\'') - s;
1469
1470                 q = p = makestrspace(len + 3, p);
1471
1472                 *q++ = '\'';
1473                 q = memcpy(q, s, len) + len;
1474                 *q++ = '\'';
1475                 s += len;
1476
1477                 STADJUST(q - p, p);
1478
1479                 len = strspn(s, "'");
1480                 if (!len)
1481                         break;
1482
1483                 q = p = makestrspace(len + 3, p);
1484
1485                 *q++ = '"';
1486                 q = memcpy(q, s, len) + len;
1487                 *q++ = '"';
1488                 s += len;
1489
1490                 STADJUST(q - p, p);
1491         } while (*s);
1492
1493         USTPUTC(0, p);
1494
1495         return stackblock();
1496 }
1497
1498
1499 /* ============ nextopt */
1500
1501 static char **argptr;                  /* argument list for builtin commands */
1502 static char *optionarg;                /* set by nextopt (like getopt) */
1503 static char *optptr;                   /* used by nextopt */
1504
1505 /*
1506  * XXX - should get rid of.  have all builtins use getopt(3).  the
1507  * library getopt must have the BSD extension static variable "optreset"
1508  * otherwise it can't be used within the shell safely.
1509  *
1510  * Standard option processing (a la getopt) for builtin routines.  The
1511  * only argument that is passed to nextopt is the option string; the
1512  * other arguments are unnecessary.  It return the character, or '\0' on
1513  * end of input.
1514  */
1515 static int
1516 nextopt(const char *optstring)
1517 {
1518         char *p;
1519         const char *q;
1520         char c;
1521
1522         p = optptr;
1523         if (p == NULL || *p == '\0') {
1524                 p = *argptr;
1525                 if (p == NULL || *p != '-' || *++p == '\0')
1526                         return '\0';
1527                 argptr++;
1528                 if (LONE_DASH(p))        /* check for "--" */
1529                         return '\0';
1530         }
1531         c = *p++;
1532         for (q = optstring; *q != c; ) {
1533                 if (*q == '\0')
1534                         ash_msg_and_raise_error("illegal option -%c", c);
1535                 if (*++q == ':')
1536                         q++;
1537         }
1538         if (*++q == ':') {
1539                 if (*p == '\0' && (p = *argptr++) == NULL)
1540                         ash_msg_and_raise_error("no arg for -%c option", c);
1541                 optionarg = p;
1542                 p = NULL;
1543         }
1544         optptr = p;
1545         return c;
1546 }
1547
1548
1549 /* ============ Math support definitions */
1550
1551 #if ENABLE_ASH_MATH_SUPPORT_64
1552 typedef int64_t arith_t;
1553 #define arith_t_type long long
1554 #else
1555 typedef long arith_t;
1556 #define arith_t_type long
1557 #endif
1558
1559 #if ENABLE_ASH_MATH_SUPPORT
1560 static arith_t dash_arith(const char *);
1561 static arith_t arith(const char *expr, int *perrcode);
1562 #endif
1563
1564 #if ENABLE_ASH_RANDOM_SUPPORT
1565 static unsigned long rseed;
1566 #ifndef DYNAMIC_VAR
1567 #define DYNAMIC_VAR
1568 #endif
1569 #endif
1570
1571
1572 /* ============ Shell variables */
1573
1574 /* flags */
1575 #define VEXPORT         0x01    /* variable is exported */
1576 #define VREADONLY       0x02    /* variable cannot be modified */
1577 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1578 #define VTEXTFIXED      0x08    /* text is statically allocated */
1579 #define VSTACK          0x10    /* text is allocated on the stack */
1580 #define VUNSET          0x20    /* the variable is not set */
1581 #define VNOFUNC         0x40    /* don't call the callback function */
1582 #define VNOSET          0x80    /* do not set variable - just readonly test */
1583 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1584 #ifdef DYNAMIC_VAR
1585 # define VDYNAMIC       0x200   /* dynamic variable */
1586 #else
1587 # define VDYNAMIC       0
1588 #endif
1589
1590 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1591 #ifdef IFS_BROKEN
1592 static const char defifsvar[] = "IFS= \t\n";
1593 #define defifs (defifsvar + 4)
1594 #else
1595 static const char defifs[] = " \t\n";
1596 #endif
1597
1598 struct shparam {
1599         int nparam;             /* # of positional parameters (without $0) */
1600         unsigned char malloc;   /* if parameter list dynamically allocated */
1601         char **p;               /* parameter list */
1602 #if ENABLE_ASH_GETOPTS
1603         int optind;             /* next parameter to be processed by getopts */
1604         int optoff;             /* used by getopts */
1605 #endif
1606 };
1607
1608 static struct shparam shellparam;      /* $@ current positional parameters */
1609
1610 /*
1611  * Free the list of positional parameters.
1612  */
1613 static void
1614 freeparam(volatile struct shparam *param)
1615 {
1616         char **ap;
1617
1618         if (param->malloc) {
1619                 for (ap = param->p; *ap; ap++)
1620                         free(*ap);
1621                 free(param->p);
1622         }
1623 }
1624
1625 #if ENABLE_ASH_GETOPTS
1626 static void
1627 getoptsreset(const char *value)
1628 {
1629         shellparam.optind = number(value);
1630         shellparam.optoff = -1;
1631 }
1632 #endif
1633
1634 struct var {
1635         struct var *next;               /* next entry in hash list */
1636         int flags;                      /* flags are defined above */
1637         const char *text;               /* name=value */
1638         void (*func)(const char *);     /* function to be called when  */
1639                                         /* the variable gets set/unset */
1640 };
1641
1642 struct localvar {
1643         struct localvar *next;          /* next local variable in list */
1644         struct var *vp;                 /* the variable that was made local */
1645         int flags;                      /* saved flags */
1646         const char *text;               /* saved text */
1647 };
1648
1649 /* Forward decls for varinit[] */
1650 #if ENABLE_LOCALE_SUPPORT
1651 static void
1652 change_lc_all(const char *value)
1653 {
1654         if (value && *value != '\0')
1655                 setlocale(LC_ALL, value);
1656 }
1657 static void
1658 change_lc_ctype(const char *value)
1659 {
1660         if (value && *value != '\0')
1661                 setlocale(LC_CTYPE, value);
1662 }
1663 #endif
1664 #if ENABLE_ASH_MAIL
1665 static void chkmail(void);
1666 static void changemail(const char *);
1667 #endif
1668 static void changepath(const char *);
1669 #if ENABLE_ASH_RANDOM_SUPPORT
1670 static void change_random(const char *);
1671 #endif
1672
1673 static struct var varinit[] = {
1674 #ifdef IFS_BROKEN
1675         { NULL, VSTRFIXED|VTEXTFIXED,           defifsvar,      NULL },
1676 #else
1677         { NULL, VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS\0",        NULL },
1678 #endif
1679 #if ENABLE_ASH_MAIL
1680         { NULL, VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL\0",       changemail },
1681         { NULL, VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH\0",   changemail },
1682 #endif
1683         { NULL, VSTRFIXED|VTEXTFIXED,           defpathvar,     changepath },
1684         { NULL, VSTRFIXED|VTEXTFIXED,           "PS1=$ ",       NULL },
1685         { NULL, VSTRFIXED|VTEXTFIXED,           "PS2=> ",       NULL },
1686         { NULL, VSTRFIXED|VTEXTFIXED,           "PS4=+ ",       NULL },
1687 #if ENABLE_ASH_GETOPTS
1688         { NULL, VSTRFIXED|VTEXTFIXED,           "OPTIND=1",     getoptsreset },
1689 #endif
1690 #if ENABLE_ASH_RANDOM_SUPPORT
1691         { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1692 #endif
1693 #if ENABLE_LOCALE_SUPPORT
1694         { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0",    change_lc_all },
1695         { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0",  change_lc_ctype },
1696 #endif
1697 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1698         { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0",  NULL },
1699 #endif
1700 };
1701
1702 #define vifs varinit[0]
1703 #if ENABLE_ASH_MAIL
1704 #define vmail (&vifs)[1]
1705 #define vmpath (&vmail)[1]
1706 #else
1707 #define vmpath vifs
1708 #endif
1709 #define vpath (&vmpath)[1]
1710 #define vps1 (&vpath)[1]
1711 #define vps2 (&vps1)[1]
1712 #define vps4 (&vps2)[1]
1713 #define voptind (&vps4)[1]
1714 #if ENABLE_ASH_GETOPTS
1715 #define vrandom (&voptind)[1]
1716 #else
1717 #define vrandom (&vps4)[1]
1718 #endif
1719 #define defpath (defpathvar + 5)
1720
1721 /*
1722  * The following macros access the values of the above variables.
1723  * They have to skip over the name.  They return the null string
1724  * for unset variables.
1725  */
1726 #define ifsval()        (vifs.text + 4)
1727 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1728 #define mailval()       (vmail.text + 5)
1729 #define mpathval()      (vmpath.text + 9)
1730 #define pathval()       (vpath.text + 5)
1731 #define ps1val()        (vps1.text + 4)
1732 #define ps2val()        (vps2.text + 4)
1733 #define ps4val()        (vps4.text + 4)
1734 #define optindval()     (voptind.text + 7)
1735
1736 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1737
1738 /*
1739  * The parsefile structure pointed to by the global variable parsefile
1740  * contains information about the current file being read.
1741  */
1742 struct redirtab {
1743         struct redirtab *next;
1744         int renamed[10];
1745         int nullredirs;
1746 };
1747
1748 static struct redirtab *redirlist;
1749 static int nullredirs;
1750 extern char **environ;
1751 static int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1752
1753 #define VTABSIZE 39
1754
1755 static struct var *vartab[VTABSIZE];
1756
1757 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
1758 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
1759
1760 /*
1761  * Return of a legal variable name (a letter or underscore followed by zero or
1762  * more letters, underscores, and digits).
1763  */
1764 static char *
1765 endofname(const char *name)
1766 {
1767         char *p;
1768
1769         p = (char *) name;
1770         if (!is_name(*p))
1771                 return p;
1772         while (*++p) {
1773                 if (!is_in_name(*p))
1774                         break;
1775         }
1776         return p;
1777 }
1778
1779 /*
1780  * Compares two strings up to the first = or '\0'.  The first
1781  * string must be terminated by '='; the second may be terminated by
1782  * either '=' or '\0'.
1783  */
1784 static int
1785 varcmp(const char *p, const char *q)
1786 {
1787         int c, d;
1788
1789         while ((c = *p) == (d = *q)) {
1790                 if (!c || c == '=')
1791                         goto out;
1792                 p++;
1793                 q++;
1794         }
1795         if (c == '=')
1796                 c = '\0';
1797         if (d == '=')
1798                 d = '\0';
1799  out:
1800         return c - d;
1801 }
1802
1803 static int
1804 varequal(const char *a, const char *b)
1805 {
1806         return !varcmp(a, b);
1807 }
1808
1809 /*
1810  * Find the appropriate entry in the hash table from the name.
1811  */
1812 static struct var **
1813 hashvar(const char *p)
1814 {
1815         unsigned hashval;
1816
1817         hashval = ((unsigned char) *p) << 4;
1818         while (*p && *p != '=')
1819                 hashval += (unsigned char) *p++;
1820         return &vartab[hashval % VTABSIZE];
1821 }
1822
1823 static int
1824 vpcmp(const void *a, const void *b)
1825 {
1826         return varcmp(*(const char **)a, *(const char **)b);
1827 }
1828
1829 /*
1830  * This routine initializes the builtin variables.
1831  */
1832 static void
1833 initvar(void)
1834 {
1835         struct var *vp;
1836         struct var *end;
1837         struct var **vpp;
1838
1839         /*
1840          * PS1 depends on uid
1841          */
1842 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1843         vps1.text = "PS1=\\w \\$ ";
1844 #else
1845         if (!geteuid())
1846                 vps1.text = "PS1=# ";
1847 #endif
1848         vp = varinit;
1849         end = vp + sizeof(varinit) / sizeof(varinit[0]);
1850         do {
1851                 vpp = hashvar(vp->text);
1852                 vp->next = *vpp;
1853                 *vpp = vp;
1854         } while (++vp < end);
1855 }
1856
1857 static struct var **
1858 findvar(struct var **vpp, const char *name)
1859 {
1860         for (; *vpp; vpp = &(*vpp)->next) {
1861                 if (varequal((*vpp)->text, name)) {
1862                         break;
1863                 }
1864         }
1865         return vpp;
1866 }
1867
1868 /*
1869  * Find the value of a variable.  Returns NULL if not set.
1870  */
1871 static char *
1872 lookupvar(const char *name)
1873 {
1874         struct var *v;
1875
1876         v = *findvar(hashvar(name), name);
1877         if (v) {
1878 #ifdef DYNAMIC_VAR
1879         /*
1880          * Dynamic variables are implemented roughly the same way they are
1881          * in bash. Namely, they're "special" so long as they aren't unset.
1882          * As soon as they're unset, they're no longer dynamic, and dynamic
1883          * lookup will no longer happen at that point. -- PFM.
1884          */
1885                 if ((v->flags & VDYNAMIC))
1886                         (*v->func)(NULL);
1887 #endif
1888                 if (!(v->flags & VUNSET))
1889                         return strchrnul(v->text, '=') + 1;
1890         }
1891         return NULL;
1892 }
1893
1894 /*
1895  * Search the environment of a builtin command.
1896  */
1897 static char *
1898 bltinlookup(const char *name)
1899 {
1900         struct strlist *sp;
1901
1902         for (sp = cmdenviron; sp; sp = sp->next) {
1903                 if (varequal(sp->text, name))
1904                         return strchrnul(sp->text, '=') + 1;
1905         }
1906         return lookupvar(name);
1907 }
1908
1909 /*
1910  * Same as setvar except that the variable and value are passed in
1911  * the first argument as name=value.  Since the first argument will
1912  * be actually stored in the table, it should not be a string that
1913  * will go away.
1914  * Called with interrupts off.
1915  */
1916 static void
1917 setvareq(char *s, int flags)
1918 {
1919         struct var *vp, **vpp;
1920
1921         vpp = hashvar(s);
1922         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
1923         vp = *findvar(vpp, s);
1924         if (vp) {
1925                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
1926                         const char *n;
1927
1928                         if (flags & VNOSAVE)
1929                                 free(s);
1930                         n = vp->text;
1931                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
1932                 }
1933
1934                 if (flags & VNOSET)
1935                         return;
1936
1937                 if (vp->func && (flags & VNOFUNC) == 0)
1938                         (*vp->func)(strchrnul(s, '=') + 1);
1939
1940                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
1941                         free((char*)vp->text);
1942
1943                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
1944         } else {
1945                 if (flags & VNOSET)
1946                         return;
1947                 /* not found */
1948                 vp = ckmalloc(sizeof(*vp));
1949                 vp->next = *vpp;
1950                 vp->func = NULL;
1951                 *vpp = vp;
1952         }
1953         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
1954                 s = ckstrdup(s);
1955         vp->text = s;
1956         vp->flags = flags;
1957 }
1958
1959 /*
1960  * Set the value of a variable.  The flags argument is ored with the
1961  * flags of the variable.  If val is NULL, the variable is unset.
1962  */
1963 static void
1964 setvar(const char *name, const char *val, int flags)
1965 {
1966         char *p, *q;
1967         size_t namelen;
1968         char *nameeq;
1969         size_t vallen;
1970
1971         q = endofname(name);
1972         p = strchrnul(q, '=');
1973         namelen = p - name;
1974         if (!namelen || p != q)
1975                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
1976         vallen = 0;
1977         if (val == NULL) {
1978                 flags |= VUNSET;
1979         } else {
1980                 vallen = strlen(val);
1981         }
1982         INT_OFF;
1983         nameeq = ckmalloc(namelen + vallen + 2);
1984         p = memcpy(nameeq, name, namelen) + namelen;
1985         if (val) {
1986                 *p++ = '=';
1987                 p = memcpy(p, val, vallen) + vallen;
1988         }
1989         *p = '\0';
1990         setvareq(nameeq, flags | VNOSAVE);
1991         INT_ON;
1992 }
1993
1994 #if ENABLE_ASH_GETOPTS
1995 /*
1996  * Safe version of setvar, returns 1 on success 0 on failure.
1997  */
1998 static int
1999 setvarsafe(const char *name, const char *val, int flags)
2000 {
2001         int err;
2002         volatile int saveint;
2003         struct jmploc *volatile savehandler = exception_handler;
2004         struct jmploc jmploc;
2005
2006         SAVE_INT(saveint);
2007         if (setjmp(jmploc.loc))
2008                 err = 1;
2009         else {
2010                 exception_handler = &jmploc;
2011                 setvar(name, val, flags);
2012                 err = 0;
2013         }
2014         exception_handler = savehandler;
2015         RESTORE_INT(saveint);
2016         return err;
2017 }
2018 #endif
2019
2020 /*
2021  * Unset the specified variable.
2022  */
2023 static int
2024 unsetvar(const char *s)
2025 {
2026         struct var **vpp;
2027         struct var *vp;
2028         int retval;
2029
2030         vpp = findvar(hashvar(s), s);
2031         vp = *vpp;
2032         retval = 2;
2033         if (vp) {
2034                 int flags = vp->flags;
2035
2036                 retval = 1;
2037                 if (flags & VREADONLY)
2038                         goto out;
2039 #ifdef DYNAMIC_VAR
2040                 vp->flags &= ~VDYNAMIC;
2041 #endif
2042                 if (flags & VUNSET)
2043                         goto ok;
2044                 if ((flags & VSTRFIXED) == 0) {
2045                         INT_OFF;
2046                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2047                                 free((char*)vp->text);
2048                         *vpp = vp->next;
2049                         free(vp);
2050                         INT_ON;
2051                 } else {
2052                         setvar(s, 0, 0);
2053                         vp->flags &= ~VEXPORT;
2054                 }
2055  ok:
2056                 retval = 0;
2057         }
2058  out:
2059         return retval;
2060 }
2061
2062 /*
2063  * Process a linked list of variable assignments.
2064  */
2065 static void
2066 listsetvar(struct strlist *list_set_var, int flags)
2067 {
2068         struct strlist *lp = list_set_var;
2069
2070         if (!lp)
2071                 return;
2072         INT_OFF;
2073         do {
2074                 setvareq(lp->text, flags);
2075                 lp = lp->next;
2076         } while (lp);
2077         INT_ON;
2078 }
2079
2080 /*
2081  * Generate a list of variables satisfying the given conditions.
2082  */
2083 static char **
2084 listvars(int on, int off, char ***end)
2085 {
2086         struct var **vpp;
2087         struct var *vp;
2088         char **ep;
2089         int mask;
2090
2091         STARTSTACKSTR(ep);
2092         vpp = vartab;
2093         mask = on | off;
2094         do {
2095                 for (vp = *vpp; vp; vp = vp->next) {
2096                         if ((vp->flags & mask) == on) {
2097                                 if (ep == stackstrend())
2098                                         ep = growstackstr();
2099                                 *ep++ = (char *) vp->text;
2100                         }
2101                 }
2102         } while (++vpp < vartab + VTABSIZE);
2103         if (ep == stackstrend())
2104                 ep = growstackstr();
2105         if (end)
2106                 *end = ep;
2107         *ep++ = NULL;
2108         return grabstackstr(ep);
2109 }
2110
2111
2112 /* ============ Path search helper
2113  *
2114  * The variable path (passed by reference) should be set to the start
2115  * of the path before the first call; padvance will update
2116  * this value as it proceeds.  Successive calls to padvance will return
2117  * the possible path expansions in sequence.  If an option (indicated by
2118  * a percent sign) appears in the path entry then the global variable
2119  * pathopt will be set to point to it; otherwise pathopt will be set to
2120  * NULL.
2121  */
2122 static const char *pathopt;     /* set by padvance */
2123
2124 static char *
2125 padvance(const char **path, const char *name)
2126 {
2127         const char *p;
2128         char *q;
2129         const char *start;
2130         size_t len;
2131
2132         if (*path == NULL)
2133                 return NULL;
2134         start = *path;
2135         for (p = start; *p && *p != ':' && *p != '%'; p++);
2136         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2137         while (stackblocksize() < len)
2138                 growstackblock();
2139         q = stackblock();
2140         if (p != start) {
2141                 memcpy(q, start, p - start);
2142                 q += p - start;
2143                 *q++ = '/';
2144         }
2145         strcpy(q, name);
2146         pathopt = NULL;
2147         if (*p == '%') {
2148                 pathopt = ++p;
2149                 while (*p && *p != ':') p++;
2150         }
2151         if (*p == ':')
2152                 *path = p + 1;
2153         else
2154                 *path = NULL;
2155         return stalloc(len);
2156 }
2157
2158
2159 /* ============ Prompt */
2160
2161 static int doprompt;                   /* if set, prompt the user */
2162 static int needprompt;                 /* true if interactive and at start of line */
2163
2164 #if ENABLE_FEATURE_EDITING
2165 static line_input_t *line_input_state;
2166 static const char *cmdedit_prompt;
2167 static void
2168 putprompt(const char *s)
2169 {
2170         if (ENABLE_ASH_EXPAND_PRMT) {
2171                 free((char*)cmdedit_prompt);
2172                 cmdedit_prompt = ckstrdup(s);
2173                 return;
2174         }
2175         cmdedit_prompt = s;
2176 }
2177 #else
2178 static void
2179 putprompt(const char *s)
2180 {
2181         out2str(s);
2182 }
2183 #endif
2184
2185 #if ENABLE_ASH_EXPAND_PRMT
2186 /* expandstr() needs parsing machinery, so it is far away ahead... */
2187 static const char *expandstr(const char *ps);
2188 #else
2189 #define expandstr(s) s
2190 #endif
2191
2192 static void
2193 setprompt(int whichprompt)
2194 {
2195         const char *prompt;
2196 #if ENABLE_ASH_EXPAND_PRMT
2197         struct stackmark smark;
2198 #endif
2199
2200         needprompt = 0;
2201
2202         switch (whichprompt) {
2203         case 1:
2204                 prompt = ps1val();
2205                 break;
2206         case 2:
2207                 prompt = ps2val();
2208                 break;
2209         default:                        /* 0 */
2210                 prompt = nullstr;
2211         }
2212 #if ENABLE_ASH_EXPAND_PRMT
2213         setstackmark(&smark);
2214         stalloc(stackblocksize());
2215 #endif
2216         putprompt(expandstr(prompt));
2217 #if ENABLE_ASH_EXPAND_PRMT
2218         popstackmark(&smark);
2219 #endif
2220 }
2221
2222
2223 /* ============ The cd and pwd commands */
2224
2225 #define CD_PHYSICAL 1
2226 #define CD_PRINT 2
2227
2228 static int docd(const char *, int);
2229
2230 static char *curdir = nullstr;          /* current working directory */
2231 static char *physdir = nullstr;         /* physical working directory */
2232
2233 static int
2234 cdopt(void)
2235 {
2236         int flags = 0;
2237         int i, j;
2238
2239         j = 'L';
2240         while ((i = nextopt("LP"))) {
2241                 if (i != j) {
2242                         flags ^= CD_PHYSICAL;
2243                         j = i;
2244                 }
2245         }
2246
2247         return flags;
2248 }
2249
2250 /*
2251  * Update curdir (the name of the current directory) in response to a
2252  * cd command.
2253  */
2254 static const char *
2255 updatepwd(const char *dir)
2256 {
2257         char *new;
2258         char *p;
2259         char *cdcomppath;
2260         const char *lim;
2261
2262         cdcomppath = ststrdup(dir);
2263         STARTSTACKSTR(new);
2264         if (*dir != '/') {
2265                 if (curdir == nullstr)
2266                         return 0;
2267                 new = stack_putstr(curdir, new);
2268         }
2269         new = makestrspace(strlen(dir) + 2, new);
2270         lim = stackblock() + 1;
2271         if (*dir != '/') {
2272                 if (new[-1] != '/')
2273                         USTPUTC('/', new);
2274                 if (new > lim && *lim == '/')
2275                         lim++;
2276         } else {
2277                 USTPUTC('/', new);
2278                 cdcomppath++;
2279                 if (dir[1] == '/' && dir[2] != '/') {
2280                         USTPUTC('/', new);
2281                         cdcomppath++;
2282                         lim++;
2283                 }
2284         }
2285         p = strtok(cdcomppath, "/");
2286         while (p) {
2287                 switch (*p) {
2288                 case '.':
2289                         if (p[1] == '.' && p[2] == '\0') {
2290                                 while (new > lim) {
2291                                         STUNPUTC(new);
2292                                         if (new[-1] == '/')
2293                                                 break;
2294                                 }
2295                                 break;
2296                         }
2297                         if (p[1] == '\0')
2298                                 break;
2299                         /* fall through */
2300                 default:
2301                         new = stack_putstr(p, new);
2302                         USTPUTC('/', new);
2303                 }
2304                 p = strtok(0, "/");
2305         }
2306         if (new > lim)
2307                 STUNPUTC(new);
2308         *new = 0;
2309         return stackblock();
2310 }
2311
2312 /*
2313  * Find out what the current directory is. If we already know the current
2314  * directory, this routine returns immediately.
2315  */
2316 static char *
2317 getpwd(void)
2318 {
2319         char *dir = getcwd(0, 0);
2320         return dir ? dir : nullstr;
2321 }
2322
2323 static void
2324 setpwd(const char *val, int setold)
2325 {
2326         char *oldcur, *dir;
2327
2328         oldcur = dir = curdir;
2329
2330         if (setold) {
2331                 setvar("OLDPWD", oldcur, VEXPORT);
2332         }
2333         INT_OFF;
2334         if (physdir != nullstr) {
2335                 if (physdir != oldcur)
2336                         free(physdir);
2337                 physdir = nullstr;
2338         }
2339         if (oldcur == val || !val) {
2340                 char *s = getpwd();
2341                 physdir = s;
2342                 if (!val)
2343                         dir = s;
2344         } else
2345                 dir = ckstrdup(val);
2346         if (oldcur != dir && oldcur != nullstr) {
2347                 free(oldcur);
2348         }
2349         curdir = dir;
2350         INT_ON;
2351         setvar("PWD", dir, VEXPORT);
2352 }
2353
2354 static void hashcd(void);
2355
2356 /*
2357  * Actually do the chdir.  We also call hashcd to let the routines in exec.c
2358  * know that the current directory has changed.
2359  */
2360 static int
2361 docd(const char *dest, int flags)
2362 {
2363         const char *dir = 0;
2364         int err;
2365
2366         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2367
2368         INT_OFF;
2369         if (!(flags & CD_PHYSICAL)) {
2370                 dir = updatepwd(dest);
2371                 if (dir)
2372                         dest = dir;
2373         }
2374         err = chdir(dest);
2375         if (err)
2376                 goto out;
2377         setpwd(dir, 1);
2378         hashcd();
2379  out:
2380         INT_ON;
2381         return err;
2382 }
2383
2384 static int
2385 cdcmd(int argc, char **argv)
2386 {
2387         const char *dest;
2388         const char *path;
2389         const char *p;
2390         char c;
2391         struct stat statb;
2392         int flags;
2393
2394         flags = cdopt();
2395         dest = *argptr;
2396         if (!dest)
2397                 dest = bltinlookup(homestr);
2398         else if (LONE_DASH(dest)) {
2399                 dest = bltinlookup("OLDPWD");
2400                 flags |= CD_PRINT;
2401         }
2402         if (!dest)
2403                 dest = nullstr;
2404         if (*dest == '/')
2405                 goto step7;
2406         if (*dest == '.') {
2407                 c = dest[1];
2408  dotdot:
2409                 switch (c) {
2410                 case '\0':
2411                 case '/':
2412                         goto step6;
2413                 case '.':
2414                         c = dest[2];
2415                         if (c != '.')
2416                                 goto dotdot;
2417                 }
2418         }
2419         if (!*dest)
2420                 dest = ".";
2421         path = bltinlookup("CDPATH");
2422         if (!path) {
2423  step6:
2424  step7:
2425                 p = dest;
2426                 goto docd;
2427         }
2428         do {
2429                 c = *path;
2430                 p = padvance(&path, dest);
2431                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2432                         if (c && c != ':')
2433                                 flags |= CD_PRINT;
2434  docd:
2435                         if (!docd(p, flags))
2436                                 goto out;
2437                         break;
2438                 }
2439         } while (path);
2440         ash_msg_and_raise_error("can't cd to %s", dest);
2441         /* NOTREACHED */
2442  out:
2443         if (flags & CD_PRINT)
2444                 out1fmt(snlfmt, curdir);
2445         return 0;
2446 }
2447
2448 static int
2449 pwdcmd(int argc, char **argv)
2450 {
2451         int flags;
2452         const char *dir = curdir;
2453
2454         flags = cdopt();
2455         if (flags) {
2456                 if (physdir == nullstr)
2457                         setpwd(dir, 0);
2458                 dir = physdir;
2459         }
2460         out1fmt(snlfmt, dir);
2461         return 0;
2462 }
2463
2464
2465 /* ============ ... */
2466
2467 #define IBUFSIZ (BUFSIZ + 1)
2468 #define basebuf bb_common_bufsiz1       /* buffer for top level input file */
2469
2470 /* Syntax classes */
2471 #define CWORD 0                 /* character is nothing special */
2472 #define CNL 1                   /* newline character */
2473 #define CBACK 2                 /* a backslash character */
2474 #define CSQUOTE 3               /* single quote */
2475 #define CDQUOTE 4               /* double quote */
2476 #define CENDQUOTE 5             /* a terminating quote */
2477 #define CBQUOTE 6               /* backwards single quote */
2478 #define CVAR 7                  /* a dollar sign */
2479 #define CENDVAR 8               /* a '}' character */
2480 #define CLP 9                   /* a left paren in arithmetic */
2481 #define CRP 10                  /* a right paren in arithmetic */
2482 #define CENDFILE 11             /* end of file */
2483 #define CCTL 12                 /* like CWORD, except it must be escaped */
2484 #define CSPCL 13                /* these terminate a word */
2485 #define CIGN 14                 /* character should be ignored */
2486
2487 #if ENABLE_ASH_ALIAS
2488 #define SYNBASE 130
2489 #define PEOF -130
2490 #define PEOA -129
2491 #define PEOA_OR_PEOF PEOA
2492 #else
2493 #define SYNBASE 129
2494 #define PEOF -129
2495 #define PEOA_OR_PEOF PEOF
2496 #endif
2497
2498 /* number syntax index */
2499 #define BASESYNTAX 0    /* not in quotes */
2500 #define DQSYNTAX   1    /* in double quotes */
2501 #define SQSYNTAX   2    /* in single quotes */
2502 #define ARISYNTAX  3    /* in arithmetic */
2503
2504 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2505 #define USE_SIT_FUNCTION
2506 #endif
2507
2508 #if ENABLE_ASH_MATH_SUPPORT
2509 static const char S_I_T[][4] = {
2510 #if ENABLE_ASH_ALIAS
2511         { CSPCL, CIGN, CIGN, CIGN },            /* 0, PEOA */
2512 #endif
2513         { CSPCL, CWORD, CWORD, CWORD },         /* 1, ' ' */
2514         { CNL, CNL, CNL, CNL },                 /* 2, \n */
2515         { CWORD, CCTL, CCTL, CWORD },           /* 3, !*-/:=?[]~ */
2516         { CDQUOTE, CENDQUOTE, CWORD, CWORD },   /* 4, '"' */
2517         { CVAR, CVAR, CWORD, CVAR },            /* 5, $ */
2518         { CSQUOTE, CWORD, CENDQUOTE, CWORD },   /* 6, "'" */
2519         { CSPCL, CWORD, CWORD, CLP },           /* 7, ( */
2520         { CSPCL, CWORD, CWORD, CRP },           /* 8, ) */
2521         { CBACK, CBACK, CCTL, CBACK },          /* 9, \ */
2522         { CBQUOTE, CBQUOTE, CWORD, CBQUOTE },   /* 10, ` */
2523         { CENDVAR, CENDVAR, CWORD, CENDVAR },   /* 11, } */
2524 #ifndef USE_SIT_FUNCTION
2525         { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2526         { CWORD, CWORD, CWORD, CWORD },         /* 13, 0-9A-Za-z */
2527         { CCTL, CCTL, CCTL, CCTL }              /* 14, CTLESC ... */
2528 #endif
2529 };
2530 #else
2531 static const char S_I_T[][3] = {
2532 #if ENABLE_ASH_ALIAS
2533         { CSPCL, CIGN, CIGN },                  /* 0, PEOA */
2534 #endif
2535         { CSPCL, CWORD, CWORD },                /* 1, ' ' */
2536         { CNL, CNL, CNL },                      /* 2, \n */
2537         { CWORD, CCTL, CCTL },                  /* 3, !*-/:=?[]~ */
2538         { CDQUOTE, CENDQUOTE, CWORD },          /* 4, '"' */
2539         { CVAR, CVAR, CWORD },                  /* 5, $ */
2540         { CSQUOTE, CWORD, CENDQUOTE },          /* 6, "'" */
2541         { CSPCL, CWORD, CWORD },                /* 7, ( */
2542         { CSPCL, CWORD, CWORD },                /* 8, ) */
2543         { CBACK, CBACK, CCTL },                 /* 9, \ */
2544         { CBQUOTE, CBQUOTE, CWORD },            /* 10, ` */
2545         { CENDVAR, CENDVAR, CWORD },            /* 11, } */
2546 #ifndef USE_SIT_FUNCTION
2547         { CENDFILE, CENDFILE, CENDFILE },       /* 12, PEOF */
2548         { CWORD, CWORD, CWORD },                /* 13, 0-9A-Za-z */
2549         { CCTL, CCTL, CCTL }                    /* 14, CTLESC ... */
2550 #endif
2551 };
2552 #endif /* ASH_MATH_SUPPORT */
2553
2554 #ifdef USE_SIT_FUNCTION
2555
2556 static int
2557 SIT(int c, int syntax)
2558 {
2559         static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2560 #if ENABLE_ASH_ALIAS
2561         static const char syntax_index_table[] = {
2562                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2563                 7, 8, 3, 3, 3, 3, 1, 1,         /* "()*-/:;<" */
2564                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2565                 11, 3                           /* "}~" */
2566         };
2567 #else
2568         static const char syntax_index_table[] = {
2569                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2570                 6, 7, 2, 2, 2, 2, 0, 0,         /* "()*-/:;<" */
2571                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2572                 10, 2                           /* "}~" */
2573         };
2574 #endif
2575         const char *s;
2576         int indx;
2577
2578         if (c == PEOF)          /* 2^8+2 */
2579                 return CENDFILE;
2580 #if ENABLE_ASH_ALIAS
2581         if (c == PEOA)          /* 2^8+1 */
2582                 indx = 0;
2583         else
2584 #endif
2585 #define U_C(c) ((unsigned char)(c))
2586
2587         if ((unsigned char)c >= (unsigned char)(CTLESC)
2588          && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2589         ) {
2590                 return CCTL;
2591         } else {
2592                 s = strchr(spec_symbls, c);
2593                 if (s == NULL || *s == '\0')
2594                         return CWORD;
2595                 indx = syntax_index_table[(s - spec_symbls)];
2596         }
2597         return S_I_T[indx][syntax];
2598 }
2599
2600 #else   /* !USE_SIT_FUNCTION */
2601
2602 #if ENABLE_ASH_ALIAS
2603 #define CSPCL_CIGN_CIGN_CIGN                     0
2604 #define CSPCL_CWORD_CWORD_CWORD                  1
2605 #define CNL_CNL_CNL_CNL                          2
2606 #define CWORD_CCTL_CCTL_CWORD                    3
2607 #define CDQUOTE_CENDQUOTE_CWORD_CWORD            4
2608 #define CVAR_CVAR_CWORD_CVAR                     5
2609 #define CSQUOTE_CWORD_CENDQUOTE_CWORD            6
2610 #define CSPCL_CWORD_CWORD_CLP                    7
2611 #define CSPCL_CWORD_CWORD_CRP                    8
2612 #define CBACK_CBACK_CCTL_CBACK                   9
2613 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE           10
2614 #define CENDVAR_CENDVAR_CWORD_CENDVAR           11
2615 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE     12
2616 #define CWORD_CWORD_CWORD_CWORD                 13
2617 #define CCTL_CCTL_CCTL_CCTL                     14
2618 #else
2619 #define CSPCL_CWORD_CWORD_CWORD                  0
2620 #define CNL_CNL_CNL_CNL                          1
2621 #define CWORD_CCTL_CCTL_CWORD                    2
2622 #define CDQUOTE_CENDQUOTE_CWORD_CWORD            3
2623 #define CVAR_CVAR_CWORD_CVAR                     4
2624 #define CSQUOTE_CWORD_CENDQUOTE_CWORD            5
2625 #define CSPCL_CWORD_CWORD_CLP                    6
2626 #define CSPCL_CWORD_CWORD_CRP                    7
2627 #define CBACK_CBACK_CCTL_CBACK                   8
2628 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE            9
2629 #define CENDVAR_CENDVAR_CWORD_CENDVAR           10
2630 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE     11
2631 #define CWORD_CWORD_CWORD_CWORD                 12
2632 #define CCTL_CCTL_CCTL_CCTL                     13
2633 #endif
2634
2635 static const char syntax_index_table[258] = {
2636         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2637         /*   0  PEOF */      CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2638 #if ENABLE_ASH_ALIAS
2639         /*   1  PEOA */      CSPCL_CIGN_CIGN_CIGN,
2640 #endif
2641         /*   2  -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2642         /*   3  -127 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
2643         /*   4  -126 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
2644         /*   5  -125 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
2645         /*   6  -124 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
2646         /*   7  -123 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
2647         /*   8  -122 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
2648         /*   9  -121 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
2649         /*  10  -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2650         /*  11  -119      */ CWORD_CWORD_CWORD_CWORD,
2651         /*  12  -118      */ CWORD_CWORD_CWORD_CWORD,
2652         /*  13  -117      */ CWORD_CWORD_CWORD_CWORD,
2653         /*  14  -116      */ CWORD_CWORD_CWORD_CWORD,
2654         /*  15  -115      */ CWORD_CWORD_CWORD_CWORD,
2655         /*  16  -114      */ CWORD_CWORD_CWORD_CWORD,
2656         /*  17  -113      */ CWORD_CWORD_CWORD_CWORD,
2657         /*  18  -112      */ CWORD_CWORD_CWORD_CWORD,
2658         /*  19  -111      */ CWORD_CWORD_CWORD_CWORD,
2659         /*  20  -110      */ CWORD_CWORD_CWORD_CWORD,
2660         /*  21  -109      */ CWORD_CWORD_CWORD_CWORD,
2661         /*  22  -108      */ CWORD_CWORD_CWORD_CWORD,
2662         /*  23  -107      */ CWORD_CWORD_CWORD_CWORD,
2663         /*  24  -106      */ CWORD_CWORD_CWORD_CWORD,
2664         /*  25  -105      */ CWORD_CWORD_CWORD_CWORD,
2665         /*  26  -104      */ CWORD_CWORD_CWORD_CWORD,
2666         /*  27  -103      */ CWORD_CWORD_CWORD_CWORD,
2667         /*  28  -102      */ CWORD_CWORD_CWORD_CWORD,
2668         /*  29  -101      */ CWORD_CWORD_CWORD_CWORD,
2669         /*  30  -100      */ CWORD_CWORD_CWORD_CWORD,
2670         /*  31   -99      */ CWORD_CWORD_CWORD_CWORD,
2671         /*  32   -98      */ CWORD_CWORD_CWORD_CWORD,
2672         /*  33   -97      */ CWORD_CWORD_CWORD_CWORD,
2673         /*  34   -96      */ CWORD_CWORD_CWORD_CWORD,
2674         /*  35   -95      */ CWORD_CWORD_CWORD_CWORD,
2675         /*  36   -94      */ CWORD_CWORD_CWORD_CWORD,
2676         /*  37   -93      */ CWORD_CWORD_CWORD_CWORD,
2677         /*  38   -92      */ CWORD_CWORD_CWORD_CWORD,
2678         /*  39   -91      */ CWORD_CWORD_CWORD_CWORD,
2679         /*  40   -90      */ CWORD_CWORD_CWORD_CWORD,
2680         /*  41   -89      */ CWORD_CWORD_CWORD_CWORD,
2681         /*  42   -88      */ CWORD_CWORD_CWORD_CWORD,
2682         /*  43   -87      */ CWORD_CWORD_CWORD_CWORD,
2683         /*  44   -86      */ CWORD_CWORD_CWORD_CWORD,
2684         /*  45   -85      */ CWORD_CWORD_CWORD_CWORD,
2685         /*  46   -84      */ CWORD_CWORD_CWORD_CWORD,
2686         /*  47   -83      */ CWORD_CWORD_CWORD_CWORD,
2687         /*  48   -82      */ CWORD_CWORD_CWORD_CWORD,
2688         /*  49   -81      */ CWORD_CWORD_CWORD_CWORD,
2689         /*  50   -80      */ CWORD_CWORD_CWORD_CWORD,
2690         /*  51   -79      */ CWORD_CWORD_CWORD_CWORD,
2691         /*  52   -78      */ CWORD_CWORD_CWORD_CWORD,
2692         /*  53   -77      */ CWORD_CWORD_CWORD_CWORD,
2693         /*  54   -76      */ CWORD_CWORD_CWORD_CWORD,
2694         /*  55   -75      */ CWORD_CWORD_CWORD_CWORD,
2695         /*  56   -74      */ CWORD_CWORD_CWORD_CWORD,
2696         /*  57   -73      */ CWORD_CWORD_CWORD_CWORD,
2697         /*  58   -72      */ CWORD_CWORD_CWORD_CWORD,
2698         /*  59   -71      */ CWORD_CWORD_CWORD_CWORD,
2699         /*  60   -70      */ CWORD_CWORD_CWORD_CWORD,
2700         /*  61   -69      */ CWORD_CWORD_CWORD_CWORD,
2701         /*  62   -68      */ CWORD_CWORD_CWORD_CWORD,
2702         /*  63   -67      */ CWORD_CWORD_CWORD_CWORD,
2703         /*  64   -66      */ CWORD_CWORD_CWORD_CWORD,
2704         /*  65   -65      */ CWORD_CWORD_CWORD_CWORD,
2705         /*  66   -64      */ CWORD_CWORD_CWORD_CWORD,
2706         /*  67   -63      */ CWORD_CWORD_CWORD_CWORD,
2707         /*  68   -62      */ CWORD_CWORD_CWORD_CWORD,
2708         /*  69   -61      */ CWORD_CWORD_CWORD_CWORD,
2709         /*  70   -60      */ CWORD_CWORD_CWORD_CWORD,
2710         /*  71   -59      */ CWORD_CWORD_CWORD_CWORD,
2711         /*  72   -58      */ CWORD_CWORD_CWORD_CWORD,
2712         /*  73   -57      */ CWORD_CWORD_CWORD_CWORD,
2713         /*  74   -56      */ CWORD_CWORD_CWORD_CWORD,
2714         /*  75   -55      */ CWORD_CWORD_CWORD_CWORD,
2715         /*  76   -54      */ CWORD_CWORD_CWORD_CWORD,
2716         /*  77   -53      */ CWORD_CWORD_CWORD_CWORD,
2717         /*  78   -52      */ CWORD_CWORD_CWORD_CWORD,
2718         /*  79   -51      */ CWORD_CWORD_CWORD_CWORD,
2719         /*  80   -50      */ CWORD_CWORD_CWORD_CWORD,
2720         /*  81   -49      */ CWORD_CWORD_CWORD_CWORD,
2721         /*  82   -48      */ CWORD_CWORD_CWORD_CWORD,
2722         /*  83   -47      */ CWORD_CWORD_CWORD_CWORD,
2723         /*  84   -46      */ CWORD_CWORD_CWORD_CWORD,
2724         /*  85   -45      */ CWORD_CWORD_CWORD_CWORD,
2725         /*  86   -44      */ CWORD_CWORD_CWORD_CWORD,
2726         /*  87   -43      */ CWORD_CWORD_CWORD_CWORD,
2727         /*  88   -42      */ CWORD_CWORD_CWORD_CWORD,
2728         /*  89   -41      */ CWORD_CWORD_CWORD_CWORD,
2729         /*  90   -40      */ CWORD_CWORD_CWORD_CWORD,
2730         /*  91   -39      */ CWORD_CWORD_CWORD_CWORD,
2731         /*  92   -38      */ CWORD_CWORD_CWORD_CWORD,
2732         /*  93   -37      */ CWORD_CWORD_CWORD_CWORD,
2733         /*  94   -36      */ CWORD_CWORD_CWORD_CWORD,
2734         /*  95   -35      */ CWORD_CWORD_CWORD_CWORD,
2735         /*  96   -34      */ CWORD_CWORD_CWORD_CWORD,
2736         /*  97   -33      */ CWORD_CWORD_CWORD_CWORD,
2737         /*  98   -32      */ CWORD_CWORD_CWORD_CWORD,
2738         /*  99   -31      */ CWORD_CWORD_CWORD_CWORD,
2739         /* 100   -30      */ CWORD_CWORD_CWORD_CWORD,
2740         /* 101   -29      */ CWORD_CWORD_CWORD_CWORD,
2741         /* 102   -28      */ CWORD_CWORD_CWORD_CWORD,
2742         /* 103   -27      */ CWORD_CWORD_CWORD_CWORD,
2743         /* 104   -26      */ CWORD_CWORD_CWORD_CWORD,
2744         /* 105   -25      */ CWORD_CWORD_CWORD_CWORD,
2745         /* 106   -24      */ CWORD_CWORD_CWORD_CWORD,
2746         /* 107   -23      */ CWORD_CWORD_CWORD_CWORD,
2747         /* 108   -22      */ CWORD_CWORD_CWORD_CWORD,
2748         /* 109   -21      */ CWORD_CWORD_CWORD_CWORD,
2749         /* 110   -20      */ CWORD_CWORD_CWORD_CWORD,
2750         /* 111   -19      */ CWORD_CWORD_CWORD_CWORD,
2751         /* 112   -18      */ CWORD_CWORD_CWORD_CWORD,
2752         /* 113   -17      */ CWORD_CWORD_CWORD_CWORD,
2753         /* 114   -16      */ CWORD_CWORD_CWORD_CWORD,
2754         /* 115   -15      */ CWORD_CWORD_CWORD_CWORD,
2755         /* 116   -14      */ CWORD_CWORD_CWORD_CWORD,
2756         /* 117   -13      */ CWORD_CWORD_CWORD_CWORD,
2757         /* 118   -12      */ CWORD_CWORD_CWORD_CWORD,
2758         /* 119   -11      */ CWORD_CWORD_CWORD_CWORD,
2759         /* 120   -10      */ CWORD_CWORD_CWORD_CWORD,
2760         /* 121    -9      */ CWORD_CWORD_CWORD_CWORD,
2761         /* 122    -8      */ CWORD_CWORD_CWORD_CWORD,
2762         /* 123    -7      */ CWORD_CWORD_CWORD_CWORD,
2763         /* 124    -6      */ CWORD_CWORD_CWORD_CWORD,
2764         /* 125    -5      */ CWORD_CWORD_CWORD_CWORD,
2765         /* 126    -4      */ CWORD_CWORD_CWORD_CWORD,
2766         /* 127    -3      */ CWORD_CWORD_CWORD_CWORD,
2767         /* 128    -2      */ CWORD_CWORD_CWORD_CWORD,
2768         /* 129    -1      */ CWORD_CWORD_CWORD_CWORD,
2769         /* 130     0      */ CWORD_CWORD_CWORD_CWORD,
2770         /* 131     1      */ CWORD_CWORD_CWORD_CWORD,
2771         /* 132     2      */ CWORD_CWORD_CWORD_CWORD,
2772         /* 133     3      */ CWORD_CWORD_CWORD_CWORD,
2773         /* 134     4      */ CWORD_CWORD_CWORD_CWORD,
2774         /* 135     5      */ CWORD_CWORD_CWORD_CWORD,
2775         /* 136     6      */ CWORD_CWORD_CWORD_CWORD,
2776         /* 137     7      */ CWORD_CWORD_CWORD_CWORD,
2777         /* 138     8      */ CWORD_CWORD_CWORD_CWORD,
2778         /* 139     9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2779         /* 140    10 "\n" */ CNL_CNL_CNL_CNL,
2780         /* 141    11      */ CWORD_CWORD_CWORD_CWORD,
2781         /* 142    12      */ CWORD_CWORD_CWORD_CWORD,
2782         /* 143    13      */ CWORD_CWORD_CWORD_CWORD,
2783         /* 144    14      */ CWORD_CWORD_CWORD_CWORD,
2784         /* 145    15      */ CWORD_CWORD_CWORD_CWORD,
2785         /* 146    16      */ CWORD_CWORD_CWORD_CWORD,
2786         /* 147    17      */ CWORD_CWORD_CWORD_CWORD,
2787         /* 148    18      */ CWORD_CWORD_CWORD_CWORD,
2788         /* 149    19      */ CWORD_CWORD_CWORD_CWORD,
2789         /* 150    20      */ CWORD_CWORD_CWORD_CWORD,
2790         /* 151    21      */ CWORD_CWORD_CWORD_CWORD,
2791         /* 152    22      */ CWORD_CWORD_CWORD_CWORD,
2792         /* 153    23      */ CWORD_CWORD_CWORD_CWORD,
2793         /* 154    24      */ CWORD_CWORD_CWORD_CWORD,
2794         /* 155    25      */ CWORD_CWORD_CWORD_CWORD,
2795         /* 156    26      */ CWORD_CWORD_CWORD_CWORD,
2796         /* 157    27      */ CWORD_CWORD_CWORD_CWORD,
2797         /* 158    28      */ CWORD_CWORD_CWORD_CWORD,
2798         /* 159    29      */ CWORD_CWORD_CWORD_CWORD,
2799         /* 160    30      */ CWORD_CWORD_CWORD_CWORD,
2800         /* 161    31      */ CWORD_CWORD_CWORD_CWORD,
2801         /* 162    32  " " */ CSPCL_CWORD_CWORD_CWORD,
2802         /* 163    33  "!" */ CWORD_CCTL_CCTL_CWORD,
2803         /* 164    34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2804         /* 165    35  "#" */ CWORD_CWORD_CWORD_CWORD,
2805         /* 166    36  "$" */ CVAR_CVAR_CWORD_CVAR,
2806         /* 167    37  "%" */ CWORD_CWORD_CWORD_CWORD,
2807         /* 168    38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2808         /* 169    39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2809         /* 170    40  "(" */ CSPCL_CWORD_CWORD_CLP,
2810         /* 171    41  ")" */ CSPCL_CWORD_CWORD_CRP,
2811         /* 172    42  "*" */ CWORD_CCTL_CCTL_CWORD,
2812         /* 173    43  "+" */ CWORD_CWORD_CWORD_CWORD,
2813         /* 174    44  "," */ CWORD_CWORD_CWORD_CWORD,
2814         /* 175    45  "-" */ CWORD_CCTL_CCTL_CWORD,
2815         /* 176    46  "." */ CWORD_CWORD_CWORD_CWORD,
2816         /* 177    47  "/" */ CWORD_CCTL_CCTL_CWORD,
2817         /* 178    48  "0" */ CWORD_CWORD_CWORD_CWORD,
2818         /* 179    49  "1" */ CWORD_CWORD_CWORD_CWORD,
2819         /* 180    50  "2" */ CWORD_CWORD_CWORD_CWORD,
2820         /* 181    51  "3" */ CWORD_CWORD_CWORD_CWORD,
2821         /* 182    52  "4" */ CWORD_CWORD_CWORD_CWORD,
2822         /* 183    53  "5" */ CWORD_CWORD_CWORD_CWORD,
2823         /* 184    54  "6" */ CWORD_CWORD_CWORD_CWORD,
2824         /* 185    55  "7" */ CWORD_CWORD_CWORD_CWORD,
2825         /* 186    56  "8" */ CWORD_CWORD_CWORD_CWORD,
2826         /* 187    57  "9" */ CWORD_CWORD_CWORD_CWORD,
2827         /* 188    58  ":" */ CWORD_CCTL_CCTL_CWORD,
2828         /* 189    59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2829         /* 190    60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2830         /* 191    61  "=" */ CWORD_CCTL_CCTL_CWORD,
2831         /* 192    62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2832         /* 193    63  "?" */ CWORD_CCTL_CCTL_CWORD,
2833         /* 194    64  "@" */ CWORD_CWORD_CWORD_CWORD,
2834         /* 195    65  "A" */ CWORD_CWORD_CWORD_CWORD,
2835         /* 196    66  "B" */ CWORD_CWORD_CWORD_CWORD,
2836         /* 197    67  "C" */ CWORD_CWORD_CWORD_CWORD,
2837         /* 198    68  "D" */ CWORD_CWORD_CWORD_CWORD,
2838         /* 199    69  "E" */ CWORD_CWORD_CWORD_CWORD,
2839         /* 200    70  "F" */ CWORD_CWORD_CWORD_CWORD,
2840         /* 201    71  "G" */ CWORD_CWORD_CWORD_CWORD,
2841         /* 202    72  "H" */ CWORD_CWORD_CWORD_CWORD,
2842         /* 203    73  "I" */ CWORD_CWORD_CWORD_CWORD,
2843         /* 204    74  "J" */ CWORD_CWORD_CWORD_CWORD,
2844         /* 205    75  "K" */ CWORD_CWORD_CWORD_CWORD,
2845         /* 206    76  "L" */ CWORD_CWORD_CWORD_CWORD,
2846         /* 207    77  "M" */ CWORD_CWORD_CWORD_CWORD,
2847         /* 208    78  "N" */ CWORD_CWORD_CWORD_CWORD,
2848         /* 209    79  "O" */ CWORD_CWORD_CWORD_CWORD,
2849         /* 210    80  "P" */ CWORD_CWORD_CWORD_CWORD,
2850         /* 211    81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2851         /* 212    82  "R" */ CWORD_CWORD_CWORD_CWORD,
2852         /* 213    83  "S" */ CWORD_CWORD_CWORD_CWORD,
2853         /* 214    84  "T" */ CWORD_CWORD_CWORD_CWORD,
2854         /* 215    85  "U" */ CWORD_CWORD_CWORD_CWORD,
2855         /* 216    86  "V" */ CWORD_CWORD_CWORD_CWORD,
2856         /* 217    87  "W" */ CWORD_CWORD_CWORD_CWORD,
2857         /* 218    88  "X" */ CWORD_CWORD_CWORD_CWORD,
2858         /* 219    89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2859         /* 220    90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2860         /* 221    91  "[" */ CWORD_CCTL_CCTL_CWORD,
2861         /* 222    92  "\" */ CBACK_CBACK_CCTL_CBACK,
2862         /* 223    93  "]" */ CWORD_CCTL_CCTL_CWORD,
2863         /* 224    94  "^" */ CWORD_CWORD_CWORD_CWORD,
2864         /* 225    95  "_" */ CWORD_CWORD_CWORD_CWORD,
2865         /* 226    96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2866         /* 227    97  "a" */ CWORD_CWORD_CWORD_CWORD,
2867         /* 228    98  "b" */ CWORD_CWORD_CWORD_CWORD,
2868         /* 229    99  "c" */ CWORD_CWORD_CWORD_CWORD,
2869         /* 230   100  "d" */ CWORD_CWORD_CWORD_CWORD,
2870         /* 231   101  "e" */ CWORD_CWORD_CWORD_CWORD,
2871         /* 232   102  "f" */ CWORD_CWORD_CWORD_CWORD,
2872         /* 233   103  "g" */ CWORD_CWORD_CWORD_CWORD,
2873         /* 234   104  "h" */ CWORD_CWORD_CWORD_CWORD,
2874         /* 235   105  "i" */ CWORD_CWORD_CWORD_CWORD,
2875         /* 236   106  "j" */ CWORD_CWORD_CWORD_CWORD,
2876         /* 237   107  "k" */ CWORD_CWORD_CWORD_CWORD,
2877         /* 238   108  "l" */ CWORD_CWORD_CWORD_CWORD,
2878         /* 239   109  "m" */ CWORD_CWORD_CWORD_CWORD,
2879         /* 240   110  "n" */ CWORD_CWORD_CWORD_CWORD,
2880         /* 241   111  "o" */ CWORD_CWORD_CWORD_CWORD,
2881         /* 242   112  "p" */ CWORD_CWORD_CWORD_CWORD,
2882         /* 243   113  "q" */ CWORD_CWORD_CWORD_CWORD,
2883         /* 244   114  "r" */ CWORD_CWORD_CWORD_CWORD,
2884         /* 245   115  "s" */ CWORD_CWORD_CWORD_CWORD,
2885         /* 246   116  "t" */ CWORD_CWORD_CWORD_CWORD,
2886         /* 247   117  "u" */ CWORD_CWORD_CWORD_CWORD,
2887         /* 248   118  "v" */ CWORD_CWORD_CWORD_CWORD,
2888         /* 249   119  "w" */ CWORD_CWORD_CWORD_CWORD,
2889         /* 250   120  "x" */ CWORD_CWORD_CWORD_CWORD,
2890         /* 251   121  "y" */ CWORD_CWORD_CWORD_CWORD,
2891         /* 252   122  "z" */ CWORD_CWORD_CWORD_CWORD,
2892         /* 253   123  "{" */ CWORD_CWORD_CWORD_CWORD,
2893         /* 254   124  "|" */ CSPCL_CWORD_CWORD_CWORD,
2894         /* 255   125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2895         /* 256   126  "~" */ CWORD_CCTL_CCTL_CWORD,
2896         /* 257   127      */ CWORD_CWORD_CWORD_CWORD,
2897 };
2898
2899 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2900
2901 #endif  /* USE_SIT_FUNCTION */
2902
2903
2904 /* ============ Alias handling */
2905
2906 #if ENABLE_ASH_ALIAS
2907
2908 #define ALIASINUSE 1
2909 #define ALIASDEAD  2
2910
2911 #define ATABSIZE 39
2912
2913 struct alias {
2914         struct alias *next;
2915         char *name;
2916         char *val;
2917         int flag;
2918 };
2919
2920 static struct alias *atab[ATABSIZE];
2921
2922 static struct alias **
2923 __lookupalias(const char *name) {
2924         unsigned int hashval;
2925         struct alias **app;
2926         const char *p;
2927         unsigned int ch;
2928
2929         p = name;
2930
2931         ch = (unsigned char)*p;
2932         hashval = ch << 4;
2933         while (ch) {
2934                 hashval += ch;
2935                 ch = (unsigned char)*++p;
2936         }
2937         app = &atab[hashval % ATABSIZE];
2938
2939         for (; *app; app = &(*app)->next) {
2940                 if (strcmp(name, (*app)->name) == 0) {
2941                         break;
2942                 }
2943         }
2944
2945         return app;
2946 }
2947
2948 static struct alias *
2949 lookupalias(const char *name, int check)
2950 {
2951         struct alias *ap = *__lookupalias(name);
2952
2953         if (check && ap && (ap->flag & ALIASINUSE))
2954                 return NULL;
2955         return ap;
2956 }
2957
2958 static struct alias *
2959 freealias(struct alias *ap)
2960 {
2961         struct alias *next;
2962
2963         if (ap->flag & ALIASINUSE) {
2964                 ap->flag |= ALIASDEAD;
2965                 return ap;
2966         }
2967
2968         next = ap->next;
2969         free(ap->name);
2970         free(ap->val);
2971         free(ap);
2972         return next;
2973 }
2974
2975 static void
2976 setalias(const char *name, const char *val)
2977 {
2978         struct alias *ap, **app;
2979
2980         app = __lookupalias(name);
2981         ap = *app;
2982         INT_OFF;
2983         if (ap) {
2984                 if (!(ap->flag & ALIASINUSE)) {
2985                         free(ap->val);
2986                 }
2987                 ap->val = ckstrdup(val);
2988                 ap->flag &= ~ALIASDEAD;
2989         } else {
2990                 /* not found */
2991                 ap = ckmalloc(sizeof(struct alias));
2992                 ap->name = ckstrdup(name);
2993                 ap->val = ckstrdup(val);
2994                 ap->flag = 0;
2995                 ap->next = 0;
2996                 *app = ap;
2997         }
2998         INT_ON;
2999 }
3000
3001 static int
3002 unalias(const char *name)
3003 {
3004         struct alias **app;
3005
3006         app = __lookupalias(name);
3007
3008         if (*app) {
3009                 INT_OFF;
3010                 *app = freealias(*app);
3011                 INT_ON;
3012                 return 0;
3013         }
3014
3015         return 1;
3016 }
3017
3018 static void
3019 rmaliases(void)
3020 {
3021         struct alias *ap, **app;
3022         int i;
3023
3024         INT_OFF;
3025         for (i = 0; i < ATABSIZE; i++) {
3026                 app = &atab[i];
3027                 for (ap = *app; ap; ap = *app) {
3028                         *app = freealias(*app);
3029                         if (ap == *app) {
3030                                 app = &ap->next;
3031                         }
3032                 }
3033         }
3034         INT_ON;
3035 }
3036
3037 static void
3038 printalias(const struct alias *ap)
3039 {
3040         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3041 }
3042
3043 /*
3044  * TODO - sort output
3045  */
3046 static int
3047 aliascmd(int argc, char **argv)
3048 {
3049         char *n, *v;
3050         int ret = 0;
3051         struct alias *ap;
3052
3053         if (argc == 1) {
3054                 int i;
3055
3056                 for (i = 0; i < ATABSIZE; i++)
3057                         for (ap = atab[i]; ap; ap = ap->next) {
3058                                 printalias(ap);
3059                         }
3060                 return 0;
3061         }
3062         while ((n = *++argv) != NULL) {
3063                 v = strchr(n+1, '=');
3064                 if (v == NULL) { /* n+1: funny ksh stuff */
3065                         ap = *__lookupalias(n);
3066                         if (ap == NULL) {
3067                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3068                                 ret = 1;
3069                         } else
3070                                 printalias(ap);
3071                 } else {
3072                         *v++ = '\0';
3073                         setalias(n, v);
3074                 }
3075         }
3076
3077         return ret;
3078 }
3079
3080 static int
3081 unaliascmd(int argc, char **argv)
3082 {
3083         int i;
3084
3085         while ((i = nextopt("a")) != '\0') {
3086                 if (i == 'a') {
3087                         rmaliases();
3088                         return 0;
3089                 }
3090         }
3091         for (i = 0; *argptr; argptr++) {
3092                 if (unalias(*argptr)) {
3093                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3094                         i = 1;
3095                 }
3096         }
3097
3098         return i;
3099 }
3100
3101 #endif /* ASH_ALIAS */
3102
3103
3104 /* ============ jobs.c */
3105
3106 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3107 #define FORK_FG 0
3108 #define FORK_BG 1
3109 #define FORK_NOJOB 2
3110
3111 /* mode flags for showjob(s) */
3112 #define SHOW_PGID       0x01    /* only show pgid - for jobs -p */
3113 #define SHOW_PID        0x04    /* include process pid */
3114 #define SHOW_CHANGED    0x08    /* only jobs whose state has changed */
3115
3116 /*
3117  * A job structure contains information about a job.  A job is either a
3118  * single process or a set of processes contained in a pipeline.  In the
3119  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3120  * array of pids.
3121  */
3122
3123 struct procstat {
3124         pid_t   pid;            /* process id */
3125         int     status;         /* last process status from wait() */
3126         char    *cmd;           /* text of command being run */
3127 };
3128
3129 struct job {
3130         struct procstat ps0;    /* status of process */
3131         struct procstat *ps;    /* status or processes when more than one */
3132 #if JOBS
3133         int stopstatus;         /* status of a stopped job */
3134 #endif
3135         uint32_t
3136                 nprocs: 16,     /* number of processes */
3137                 state: 8,
3138 #define JOBRUNNING      0       /* at least one proc running */
3139 #define JOBSTOPPED      1       /* all procs are stopped */
3140 #define JOBDONE         2       /* all procs are completed */
3141 #if JOBS
3142                 sigint: 1,      /* job was killed by SIGINT */
3143                 jobctl: 1,      /* job running under job control */
3144 #endif
3145                 waited: 1,      /* true if this entry has been waited for */
3146                 used: 1,        /* true if this entry is in used */
3147                 changed: 1;     /* true if status has changed */
3148         struct job *prev_job;   /* previous job */
3149 };
3150
3151 static pid_t backgndpid;        /* pid of last background process */
3152 static int job_warning;         /* user was warned about stopped jobs */
3153 #if JOBS
3154 static int jobctl;              /* true if doing job control */
3155 #endif
3156
3157 static struct job *makejob(union node *, int);
3158 static int forkshell(struct job *, union node *, int);
3159 static int waitforjob(struct job *);
3160
3161 #if ! JOBS
3162 #define setjobctl(on)   /* do nothing */
3163 #else
3164 static void setjobctl(int);
3165 static void showjobs(FILE *, int);
3166 #endif
3167
3168 /*
3169  * Set the signal handler for the specified signal.  The routine figures
3170  * out what it should be set to.
3171  */
3172 static void
3173 setsignal(int signo)
3174 {
3175         int action;
3176         char *t, tsig;
3177         struct sigaction act;
3178
3179         t = trap[signo];
3180         if (t == NULL)
3181                 action = S_DFL;
3182         else if (*t != '\0')
3183                 action = S_CATCH;
3184         else
3185                 action = S_IGN;
3186         if (rootshell && action == S_DFL) {
3187                 switch (signo) {
3188                 case SIGINT:
3189                         if (iflag || minusc || sflag == 0)
3190                                 action = S_CATCH;
3191                         break;
3192                 case SIGQUIT:
3193 #if DEBUG
3194                         if (debug)
3195                                 break;
3196 #endif
3197                         /* FALLTHROUGH */
3198                 case SIGTERM:
3199                         if (iflag)
3200                                 action = S_IGN;
3201                         break;
3202 #if JOBS
3203                 case SIGTSTP:
3204                 case SIGTTOU:
3205                         if (mflag)
3206                                 action = S_IGN;
3207                         break;
3208 #endif
3209                 }
3210         }
3211
3212         t = &sigmode[signo - 1];
3213         tsig = *t;
3214         if (tsig == 0) {
3215                 /*
3216                  * current setting unknown
3217                  */
3218                 if (sigaction(signo, 0, &act) == -1) {
3219                         /*
3220                          * Pretend it worked; maybe we should give a warning
3221                          * here, but other shells don't. We don't alter
3222                          * sigmode, so that we retry every time.
3223                          */
3224                         return;
3225                 }
3226                 if (act.sa_handler == SIG_IGN) {
3227                         if (mflag
3228                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3229                         ) {
3230                                 tsig = S_IGN;   /* don't hard ignore these */
3231                         } else
3232                                 tsig = S_HARD_IGN;
3233                 } else {
3234                         tsig = S_RESET; /* force to be set */
3235                 }
3236         }
3237         if (tsig == S_HARD_IGN || tsig == action)
3238                 return;
3239         switch (action) {
3240         case S_CATCH:
3241                 act.sa_handler = onsig;
3242                 break;
3243         case S_IGN:
3244                 act.sa_handler = SIG_IGN;
3245                 break;
3246         default:
3247                 act.sa_handler = SIG_DFL;
3248         }
3249         *t = action;
3250         act.sa_flags = 0;
3251         sigfillset(&act.sa_mask);
3252         sigaction(signo, &act, 0);
3253 }
3254
3255 /* mode flags for set_curjob */
3256 #define CUR_DELETE 2
3257 #define CUR_RUNNING 1
3258 #define CUR_STOPPED 0
3259
3260 /* mode flags for dowait */
3261 #define DOWAIT_NORMAL 0
3262 #define DOWAIT_BLOCK 1
3263
3264 #if JOBS
3265 /* pgrp of shell on invocation */
3266 static int initialpgrp;
3267 static int ttyfd = -1;
3268 #endif
3269 /* array of jobs */
3270 static struct job *jobtab;
3271 /* size of array */
3272 static unsigned njobs;
3273 /* current job */
3274 static struct job *curjob;
3275 /* number of presumed living untracked jobs */
3276 static int jobless;
3277
3278 static void
3279 set_curjob(struct job *jp, unsigned mode)
3280 {
3281         struct job *jp1;
3282         struct job **jpp, **curp;
3283
3284         /* first remove from list */
3285         jpp = curp = &curjob;
3286         do {
3287                 jp1 = *jpp;
3288                 if (jp1 == jp)
3289                         break;
3290                 jpp = &jp1->prev_job;
3291         } while (1);
3292         *jpp = jp1->prev_job;
3293
3294         /* Then re-insert in correct position */
3295         jpp = curp;
3296         switch (mode) {
3297         default:
3298 #if DEBUG
3299                 abort();
3300 #endif
3301         case CUR_DELETE:
3302                 /* job being deleted */
3303                 break;
3304         case CUR_RUNNING:
3305                 /* newly created job or backgrounded job,
3306                    put after all stopped jobs. */
3307                 do {
3308                         jp1 = *jpp;
3309 #if JOBS
3310                         if (!jp1 || jp1->state != JOBSTOPPED)
3311 #endif
3312                                 break;
3313                         jpp = &jp1->prev_job;
3314                 } while (1);
3315                 /* FALLTHROUGH */
3316 #if JOBS
3317         case CUR_STOPPED:
3318 #endif
3319                 /* newly stopped job - becomes curjob */
3320                 jp->prev_job = *jpp;
3321                 *jpp = jp;
3322                 break;
3323         }
3324 }
3325
3326 #if JOBS || DEBUG
3327 static int
3328 jobno(const struct job *jp)
3329 {
3330         return jp - jobtab + 1;
3331 }
3332 #endif
3333
3334 /*
3335  * Convert a job name to a job structure.
3336  */
3337 static struct job *
3338 getjob(const char *name, int getctl)
3339 {
3340         struct job *jp;
3341         struct job *found;
3342         const char *err_msg = "No such job: %s";
3343         unsigned num;
3344         int c;
3345         const char *p;
3346         char *(*match)(const char *, const char *);
3347
3348         jp = curjob;
3349         p = name;
3350         if (!p)
3351                 goto currentjob;
3352
3353         if (*p != '%')
3354                 goto err;
3355
3356         c = *++p;
3357         if (!c)
3358                 goto currentjob;
3359
3360         if (!p[1]) {
3361                 if (c == '+' || c == '%') {
3362  currentjob:
3363                         err_msg = "No current job";
3364                         goto check;
3365                 }
3366                 if (c == '-') {
3367                         if (jp)
3368                                 jp = jp->prev_job;
3369                         err_msg = "No previous job";
3370  check:
3371                         if (!jp)
3372                                 goto err;
3373                         goto gotit;
3374                 }
3375         }
3376
3377         if (is_number(p)) {
3378                 num = atoi(p);
3379                 if (num < njobs) {
3380                         jp = jobtab + num - 1;
3381                         if (jp->used)
3382                                 goto gotit;
3383                         goto err;
3384                 }
3385         }
3386
3387         match = prefix;
3388         if (*p == '?') {
3389                 match = strstr;
3390                 p++;
3391         }
3392
3393         found = 0;
3394         while (1) {
3395                 if (!jp)
3396                         goto err;
3397                 if (match(jp->ps[0].cmd, p)) {
3398                         if (found)
3399                                 goto err;
3400                         found = jp;
3401                         err_msg = "%s: ambiguous";
3402                 }
3403                 jp = jp->prev_job;
3404         }
3405
3406  gotit:
3407 #if JOBS
3408         err_msg = "job %s not created under job control";
3409         if (getctl && jp->jobctl == 0)
3410                 goto err;
3411 #endif
3412         return jp;
3413  err:
3414         ash_msg_and_raise_error(err_msg, name);
3415 }
3416
3417 /*
3418  * Mark a job structure as unused.
3419  */
3420 static void
3421 freejob(struct job *jp)
3422 {
3423         struct procstat *ps;
3424         int i;
3425
3426         INT_OFF;
3427         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3428                 if (ps->cmd != nullstr)
3429                         free(ps->cmd);
3430         }
3431         if (jp->ps != &jp->ps0)
3432                 free(jp->ps);
3433         jp->used = 0;
3434         set_curjob(jp, CUR_DELETE);
3435         INT_ON;
3436 }
3437
3438 #if JOBS
3439 static void
3440 xtcsetpgrp(int fd, pid_t pgrp)
3441 {
3442         if (tcsetpgrp(fd, pgrp))
3443                 ash_msg_and_raise_error("cannot set tty process group (%m)");
3444 }
3445
3446 /*
3447  * Turn job control on and off.
3448  *
3449  * Note:  This code assumes that the third arg to ioctl is a character
3450  * pointer, which is true on Berkeley systems but not System V.  Since
3451  * System V doesn't have job control yet, this isn't a problem now.
3452  *
3453  * Called with interrupts off.
3454  */
3455 static void
3456 setjobctl(int on)
3457 {
3458         int fd;
3459         int pgrp;
3460
3461         if (on == jobctl || rootshell == 0)
3462                 return;
3463         if (on) {
3464                 int ofd;
3465                 ofd = fd = open(_PATH_TTY, O_RDWR);
3466                 if (fd < 0) {
3467         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3468          * That sometimes helps to acquire controlling tty.
3469          * Obviously, a workaround for bugs when someone
3470          * failed to provide a controlling tty to bash! :) */
3471                         fd += 3;
3472                         while (!isatty(fd) && --fd >= 0)
3473                                 ;
3474                 }
3475                 fd = fcntl(fd, F_DUPFD, 10);
3476                 close(ofd);
3477                 if (fd < 0)
3478                         goto out;
3479                 fcntl(fd, F_SETFD, FD_CLOEXEC);
3480                 do { /* while we are in the background */
3481                         pgrp = tcgetpgrp(fd);
3482                         if (pgrp < 0) {
3483  out:
3484                                 ash_msg("can't access tty; job control turned off");
3485                                 mflag = on = 0;
3486                                 goto close;
3487                         }
3488                         if (pgrp == getpgrp())
3489                                 break;
3490                         killpg(0, SIGTTIN);
3491                 } while (1);
3492                 initialpgrp = pgrp;
3493
3494                 setsignal(SIGTSTP);
3495                 setsignal(SIGTTOU);
3496                 setsignal(SIGTTIN);
3497                 pgrp = rootpid;
3498                 setpgid(0, pgrp);
3499                 xtcsetpgrp(fd, pgrp);
3500         } else {
3501                 /* turning job control off */
3502                 fd = ttyfd;
3503                 pgrp = initialpgrp;
3504                 /* 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 #if ENABLE_ASH_CMDCMD
6896 static int
6897 describe_command(char *command, int describe_command_verbose)
6898 #else
6899 #define describe_command_verbose 1
6900 static int
6901 describe_command(char *command)
6902 #endif
6903 {
6904         struct cmdentry entry;
6905         struct tblentry *cmdp;
6906 #if ENABLE_ASH_ALIAS
6907         const struct alias *ap;
6908 #endif
6909         const char *path = pathval();
6910
6911         if (describe_command_verbose) {
6912                 out1str(command);
6913         }
6914
6915         /* First look at the keywords */
6916         if (findkwd(command)) {
6917                 out1str(describe_command_verbose ? " is a shell keyword" : command);
6918                 goto out;
6919         }
6920
6921 #if ENABLE_ASH_ALIAS
6922         /* Then look at the aliases */
6923         ap = lookupalias(command, 0);
6924         if (ap != NULL) {
6925                 if (describe_command_verbose) {
6926                         out1fmt(" is an alias for %s", ap->val);
6927                 } else {
6928                         out1str("alias ");
6929                         printalias(ap);
6930                         return 0;
6931                 }
6932                 goto out;
6933         }
6934 #endif
6935         /* Then check if it is a tracked alias */
6936         cmdp = cmdlookup(command, 0);
6937         if (cmdp != NULL) {
6938                 entry.cmdtype = cmdp->cmdtype;
6939                 entry.u = cmdp->param;
6940         } else {
6941                 /* Finally use brute force */
6942                 find_command(command, &entry, DO_ABS, path);
6943         }
6944
6945         switch (entry.cmdtype) {
6946         case CMDNORMAL: {
6947                 int j = entry.u.index;
6948                 char *p;
6949                 if (j == -1) {
6950                         p = command;
6951                 } else {
6952                         do {
6953                                 p = padvance(&path, command);
6954                                 stunalloc(p);
6955                         } while (--j >= 0);
6956                 }
6957                 if (describe_command_verbose) {
6958                         out1fmt(" is%s %s",
6959                                 (cmdp ? " a tracked alias for" : nullstr), p
6960                         );
6961                 } else {
6962                         out1str(p);
6963                 }
6964                 break;
6965         }
6966
6967         case CMDFUNCTION:
6968                 if (describe_command_verbose) {
6969                         out1str(" is a shell function");
6970                 } else {
6971                         out1str(command);
6972                 }
6973                 break;
6974
6975         case CMDBUILTIN:
6976                 if (describe_command_verbose) {
6977                         out1fmt(" is a %sshell builtin",
6978                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
6979                                         "special " : nullstr
6980                         );
6981                 } else {
6982                         out1str(command);
6983                 }
6984                 break;
6985
6986         default:
6987                 if (describe_command_verbose) {
6988                         out1str(": not found\n");
6989                 }
6990                 return 127;
6991         }
6992  out:
6993         outstr("\n", stdout);
6994         return 0;
6995 }
6996
6997 static int
6998 typecmd(int argc, char **argv)
6999 {
7000         int i;
7001         int err = 0;
7002
7003         for (i = 1; i < argc; i++) {
7004 #if ENABLE_ASH_CMDCMD
7005                 err |= describe_command(argv[i], 1);
7006 #else
7007                 err |= describe_command(argv[i]);
7008 #endif
7009         }
7010         return err;
7011 }
7012
7013 #if ENABLE_ASH_CMDCMD
7014 static int
7015 commandcmd(int argc, char **argv)
7016 {
7017         int c;
7018         enum {
7019                 VERIFY_BRIEF = 1,
7020                 VERIFY_VERBOSE = 2,
7021         } verify = 0;
7022
7023         while ((c = nextopt("pvV")) != '\0')
7024                 if (c == 'V')
7025                         verify |= VERIFY_VERBOSE;
7026                 else if (c == 'v')
7027                         verify |= VERIFY_BRIEF;
7028 #if DEBUG
7029                 else if (c != 'p')
7030                         abort();
7031 #endif
7032         if (verify)
7033                 return describe_command(*argptr, verify - VERIFY_BRIEF);
7034
7035         return 0;
7036 }
7037 #endif
7038
7039
7040 /* ============ eval.c */
7041
7042 static int funcblocksize;          /* size of structures in function */
7043 static int funcstringsize;         /* size of strings in node */
7044 static void *funcblock;            /* block to allocate function from */
7045 static char *funcstring;           /* block to allocate strings from */
7046
7047 /* flags in argument to evaltree */
7048 #define EV_EXIT 01              /* exit after evaluating tree */
7049 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
7050 #define EV_BACKCMD 04           /* command executing within back quotes */
7051
7052 static const short nodesize[26] = {
7053         SHELL_ALIGN(sizeof(struct ncmd)),
7054         SHELL_ALIGN(sizeof(struct npipe)),
7055         SHELL_ALIGN(sizeof(struct nredir)),
7056         SHELL_ALIGN(sizeof(struct nredir)),
7057         SHELL_ALIGN(sizeof(struct nredir)),
7058         SHELL_ALIGN(sizeof(struct nbinary)),
7059         SHELL_ALIGN(sizeof(struct nbinary)),
7060         SHELL_ALIGN(sizeof(struct nbinary)),
7061         SHELL_ALIGN(sizeof(struct nif)),
7062         SHELL_ALIGN(sizeof(struct nbinary)),
7063         SHELL_ALIGN(sizeof(struct nbinary)),
7064         SHELL_ALIGN(sizeof(struct nfor)),
7065         SHELL_ALIGN(sizeof(struct ncase)),
7066         SHELL_ALIGN(sizeof(struct nclist)),
7067         SHELL_ALIGN(sizeof(struct narg)),
7068         SHELL_ALIGN(sizeof(struct narg)),
7069         SHELL_ALIGN(sizeof(struct nfile)),
7070         SHELL_ALIGN(sizeof(struct nfile)),
7071         SHELL_ALIGN(sizeof(struct nfile)),
7072         SHELL_ALIGN(sizeof(struct nfile)),
7073         SHELL_ALIGN(sizeof(struct nfile)),
7074         SHELL_ALIGN(sizeof(struct ndup)),
7075         SHELL_ALIGN(sizeof(struct ndup)),
7076         SHELL_ALIGN(sizeof(struct nhere)),
7077         SHELL_ALIGN(sizeof(struct nhere)),
7078         SHELL_ALIGN(sizeof(struct nnot)),
7079 };
7080
7081 static void calcsize(union node *n);
7082
7083 static void
7084 sizenodelist(struct nodelist *lp)
7085 {
7086         while (lp) {
7087                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7088                 calcsize(lp->n);
7089                 lp = lp->next;
7090         }
7091 }
7092
7093 static void
7094 calcsize(union node *n)
7095 {
7096         if (n == NULL)
7097                 return;
7098         funcblocksize += nodesize[n->type];
7099         switch (n->type) {
7100         case NCMD:
7101                 calcsize(n->ncmd.redirect);
7102                 calcsize(n->ncmd.args);
7103                 calcsize(n->ncmd.assign);
7104                 break;
7105         case NPIPE:
7106                 sizenodelist(n->npipe.cmdlist);
7107                 break;
7108         case NREDIR:
7109         case NBACKGND:
7110         case NSUBSHELL:
7111                 calcsize(n->nredir.redirect);
7112                 calcsize(n->nredir.n);
7113                 break;
7114         case NAND:
7115         case NOR:
7116         case NSEMI:
7117         case NWHILE:
7118         case NUNTIL:
7119                 calcsize(n->nbinary.ch2);
7120                 calcsize(n->nbinary.ch1);
7121                 break;
7122         case NIF:
7123                 calcsize(n->nif.elsepart);
7124                 calcsize(n->nif.ifpart);
7125                 calcsize(n->nif.test);
7126                 break;
7127         case NFOR:
7128                 funcstringsize += strlen(n->nfor.var) + 1;
7129                 calcsize(n->nfor.body);
7130                 calcsize(n->nfor.args);
7131                 break;
7132         case NCASE:
7133                 calcsize(n->ncase.cases);
7134                 calcsize(n->ncase.expr);
7135                 break;
7136         case NCLIST:
7137                 calcsize(n->nclist.body);
7138                 calcsize(n->nclist.pattern);
7139                 calcsize(n->nclist.next);
7140                 break;
7141         case NDEFUN:
7142         case NARG:
7143                 sizenodelist(n->narg.backquote);
7144                 funcstringsize += strlen(n->narg.text) + 1;
7145                 calcsize(n->narg.next);
7146                 break;
7147         case NTO:
7148         case NCLOBBER:
7149         case NFROM:
7150         case NFROMTO:
7151         case NAPPEND:
7152                 calcsize(n->nfile.fname);
7153                 calcsize(n->nfile.next);
7154                 break;
7155         case NTOFD:
7156         case NFROMFD:
7157                 calcsize(n->ndup.vname);
7158                 calcsize(n->ndup.next);
7159         break;
7160         case NHERE:
7161         case NXHERE:
7162                 calcsize(n->nhere.doc);
7163                 calcsize(n->nhere.next);
7164                 break;
7165         case NNOT:
7166                 calcsize(n->nnot.com);
7167                 break;
7168         };
7169 }
7170
7171 static char *
7172 nodeckstrdup(char *s)
7173 {
7174         char *rtn = funcstring;
7175
7176         strcpy(funcstring, s);
7177         funcstring += strlen(s) + 1;
7178         return rtn;
7179 }
7180
7181 static union node *copynode(union node *);
7182
7183 static struct nodelist *
7184 copynodelist(struct nodelist *lp)
7185 {
7186         struct nodelist *start;
7187         struct nodelist **lpp;
7188
7189         lpp = &start;
7190         while (lp) {
7191                 *lpp = funcblock;
7192                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7193                 (*lpp)->n = copynode(lp->n);
7194                 lp = lp->next;
7195                 lpp = &(*lpp)->next;
7196         }
7197         *lpp = NULL;
7198         return start;
7199 }
7200
7201 static union node *
7202 copynode(union node *n)
7203 {
7204         union node *new;
7205
7206         if (n == NULL)
7207                 return NULL;
7208         new = funcblock;
7209         funcblock = (char *) funcblock + nodesize[n->type];
7210
7211         switch (n->type) {
7212         case NCMD:
7213                 new->ncmd.redirect = copynode(n->ncmd.redirect);
7214                 new->ncmd.args = copynode(n->ncmd.args);
7215                 new->ncmd.assign = copynode(n->ncmd.assign);
7216                 break;
7217         case NPIPE:
7218                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7219                 new->npipe.backgnd = n->npipe.backgnd;
7220                 break;
7221         case NREDIR:
7222         case NBACKGND:
7223         case NSUBSHELL:
7224                 new->nredir.redirect = copynode(n->nredir.redirect);
7225                 new->nredir.n = copynode(n->nredir.n);
7226                 break;
7227         case NAND:
7228         case NOR:
7229         case NSEMI:
7230         case NWHILE:
7231         case NUNTIL:
7232                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7233                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7234                 break;
7235         case NIF:
7236                 new->nif.elsepart = copynode(n->nif.elsepart);
7237                 new->nif.ifpart = copynode(n->nif.ifpart);
7238                 new->nif.test = copynode(n->nif.test);
7239                 break;
7240         case NFOR:
7241                 new->nfor.var = nodeckstrdup(n->nfor.var);
7242                 new->nfor.body = copynode(n->nfor.body);
7243                 new->nfor.args = copynode(n->nfor.args);
7244                 break;
7245         case NCASE:
7246                 new->ncase.cases = copynode(n->ncase.cases);
7247                 new->ncase.expr = copynode(n->ncase.expr);
7248                 break;
7249         case NCLIST:
7250                 new->nclist.body = copynode(n->nclist.body);
7251                 new->nclist.pattern = copynode(n->nclist.pattern);
7252                 new->nclist.next = copynode(n->nclist.next);
7253                 break;
7254         case NDEFUN:
7255         case NARG:
7256                 new->narg.backquote = copynodelist(n->narg.backquote);
7257                 new->narg.text = nodeckstrdup(n->narg.text);
7258                 new->narg.next = copynode(n->narg.next);
7259                 break;
7260         case NTO:
7261         case NCLOBBER:
7262         case NFROM:
7263         case NFROMTO:
7264         case NAPPEND:
7265                 new->nfile.fname = copynode(n->nfile.fname);
7266                 new->nfile.fd = n->nfile.fd;
7267                 new->nfile.next = copynode(n->nfile.next);
7268                 break;
7269         case NTOFD:
7270         case NFROMFD:
7271                 new->ndup.vname = copynode(n->ndup.vname);
7272                 new->ndup.dupfd = n->ndup.dupfd;
7273                 new->ndup.fd = n->ndup.fd;
7274                 new->ndup.next = copynode(n->ndup.next);
7275                 break;
7276         case NHERE:
7277         case NXHERE:
7278                 new->nhere.doc = copynode(n->nhere.doc);
7279                 new->nhere.fd = n->nhere.fd;
7280                 new->nhere.next = copynode(n->nhere.next);
7281                 break;
7282         case NNOT:
7283                 new->nnot.com = copynode(n->nnot.com);
7284                 break;
7285         };
7286         new->type = n->type;
7287         return new;
7288 }
7289
7290 /*
7291  * Make a copy of a parse tree.
7292  */
7293 static struct funcnode *
7294 copyfunc(union node *n)
7295 {
7296         struct funcnode *f;
7297         size_t blocksize;
7298
7299         funcblocksize = offsetof(struct funcnode, n);
7300         funcstringsize = 0;
7301         calcsize(n);
7302         blocksize = funcblocksize;
7303         f = ckmalloc(blocksize + funcstringsize);
7304         funcblock = (char *) f + offsetof(struct funcnode, n);
7305         funcstring = (char *) f + blocksize;
7306         copynode(n);
7307         f->count = 0;
7308         return f;
7309 }
7310
7311 /*
7312  * Define a shell function.
7313  */
7314 static void
7315 defun(char *name, union node *func)
7316 {
7317         struct cmdentry entry;
7318
7319         INT_OFF;
7320         entry.cmdtype = CMDFUNCTION;
7321         entry.u.func = copyfunc(func);
7322         addcmdentry(name, &entry);
7323         INT_ON;
7324 }
7325
7326 static int evalskip;            /* set if we are skipping commands */
7327 /* reasons for skipping commands (see comment on breakcmd routine) */
7328 #define SKIPBREAK      (1 << 0)
7329 #define SKIPCONT       (1 << 1)
7330 #define SKIPFUNC       (1 << 2)
7331 #define SKIPFILE       (1 << 3)
7332 #define SKIPEVAL       (1 << 4)
7333 static int skipcount;           /* number of levels to skip */
7334 static int funcnest;            /* depth of function calls */
7335
7336 /* forward decl way out to parsing code - dotrap needs it */
7337 static int evalstring(char *s, int mask);
7338
7339 /*
7340  * Called to execute a trap.  Perhaps we should avoid entering new trap
7341  * handlers while we are executing a trap handler.
7342  */
7343 static int
7344 dotrap(void)
7345 {
7346         char *p;
7347         char *q;
7348         int i;
7349         int savestatus;
7350         int skip = 0;
7351
7352         savestatus = exitstatus;
7353         pendingsig = 0;
7354         xbarrier();
7355
7356         for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7357                 if (!*q)
7358                         continue;
7359                 *q = '\0';
7360
7361                 p = trap[i + 1];
7362                 if (!p)
7363                         continue;
7364                 skip = evalstring(p, SKIPEVAL);
7365                 exitstatus = savestatus;
7366                 if (skip)
7367                         break;
7368         }
7369
7370         return skip;
7371 }
7372
7373 /* forward declarations - evaluation is fairly recursive business... */
7374 static void evalloop(union node *, int);
7375 static void evalfor(union node *, int);
7376 static void evalcase(union node *, int);
7377 static void evalsubshell(union node *, int);
7378 static void expredir(union node *);
7379 static void evalpipe(union node *, int);
7380 static void evalcommand(union node *, int);
7381 static int evalbltin(const struct builtincmd *, int, char **);
7382 static void prehash(union node *);
7383
7384 /*
7385  * Evaluate a parse tree.  The value is left in the global variable
7386  * exitstatus.
7387  */
7388 static void
7389 evaltree(union node *n, int flags)
7390 {
7391         int checkexit = 0;
7392         void (*evalfn)(union node *, int);
7393         unsigned isor;
7394         int status;
7395         if (n == NULL) {
7396                 TRACE(("evaltree(NULL) called\n"));
7397                 goto out;
7398         }
7399         TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7400                         getpid(), n, n->type, flags));
7401         switch (n->type) {
7402         default:
7403 #if DEBUG
7404                 out1fmt("Node type = %d\n", n->type);
7405                 fflush(stdout);
7406                 break;
7407 #endif
7408         case NNOT:
7409                 evaltree(n->nnot.com, EV_TESTED);
7410                 status = !exitstatus;
7411                 goto setstatus;
7412         case NREDIR:
7413                 expredir(n->nredir.redirect);
7414                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7415                 if (!status) {
7416                         evaltree(n->nredir.n, flags & EV_TESTED);
7417                         status = exitstatus;
7418                 }
7419                 popredir(0);
7420                 goto setstatus;
7421         case NCMD:
7422                 evalfn = evalcommand;
7423  checkexit:
7424                 if (eflag && !(flags & EV_TESTED))
7425                         checkexit = ~0;
7426                 goto calleval;
7427         case NFOR:
7428                 evalfn = evalfor;
7429                 goto calleval;
7430         case NWHILE:
7431         case NUNTIL:
7432                 evalfn = evalloop;
7433                 goto calleval;
7434         case NSUBSHELL:
7435         case NBACKGND:
7436                 evalfn = evalsubshell;
7437                 goto calleval;
7438         case NPIPE:
7439                 evalfn = evalpipe;
7440                 goto checkexit;
7441         case NCASE:
7442                 evalfn = evalcase;
7443                 goto calleval;
7444         case NAND:
7445         case NOR:
7446         case NSEMI:
7447 #if NAND + 1 != NOR
7448 #error NAND + 1 != NOR
7449 #endif
7450 #if NOR + 1 != NSEMI
7451 #error NOR + 1 != NSEMI
7452 #endif
7453                 isor = n->type - NAND;
7454                 evaltree(
7455                         n->nbinary.ch1,
7456                         (flags | ((isor >> 1) - 1)) & EV_TESTED
7457                 );
7458                 if (!exitstatus == isor)
7459                         break;
7460                 if (!evalskip) {
7461                         n = n->nbinary.ch2;
7462  evaln:
7463                         evalfn = evaltree;
7464  calleval:
7465                         evalfn(n, flags);
7466                         break;
7467                 }
7468                 break;
7469         case NIF:
7470                 evaltree(n->nif.test, EV_TESTED);
7471                 if (evalskip)
7472                         break;
7473                 if (exitstatus == 0) {
7474                         n = n->nif.ifpart;
7475                         goto evaln;
7476                 } else if (n->nif.elsepart) {
7477                         n = n->nif.elsepart;
7478                         goto evaln;
7479                 }
7480                 goto success;
7481         case NDEFUN:
7482                 defun(n->narg.text, n->narg.next);
7483  success:
7484                 status = 0;
7485  setstatus:
7486                 exitstatus = status;
7487                 break;
7488         }
7489  out:
7490         if ((checkexit & exitstatus))
7491                 evalskip |= SKIPEVAL;
7492         else if (pendingsig && dotrap())
7493                 goto exexit;
7494
7495         if (flags & EV_EXIT) {
7496  exexit:
7497                 raise_exception(EXEXIT);
7498         }
7499 }
7500
7501 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7502 static
7503 #endif
7504 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7505
7506 static int loopnest;            /* current loop nesting level */
7507
7508 static void
7509 evalloop(union node *n, int flags)
7510 {
7511         int status;
7512
7513         loopnest++;
7514         status = 0;
7515         flags &= EV_TESTED;
7516         for (;;) {
7517                 int i;
7518
7519                 evaltree(n->nbinary.ch1, EV_TESTED);
7520                 if (evalskip) {
7521  skipping:
7522                         if (evalskip == SKIPCONT && --skipcount <= 0) {
7523                                 evalskip = 0;
7524                                 continue;
7525                         }
7526                         if (evalskip == SKIPBREAK && --skipcount <= 0)
7527                                 evalskip = 0;
7528                         break;
7529                 }
7530                 i = exitstatus;
7531                 if (n->type != NWHILE)
7532                         i = !i;
7533                 if (i != 0)
7534                         break;
7535                 evaltree(n->nbinary.ch2, flags);
7536                 status = exitstatus;
7537                 if (evalskip)
7538                         goto skipping;
7539         }
7540         loopnest--;
7541         exitstatus = status;
7542 }
7543
7544 static void
7545 evalfor(union node *n, int flags)
7546 {
7547         struct arglist arglist;
7548         union node *argp;
7549         struct strlist *sp;
7550         struct stackmark smark;
7551
7552         setstackmark(&smark);
7553         arglist.lastp = &arglist.list;
7554         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7555                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7556                 /* XXX */
7557                 if (evalskip)
7558                         goto out;
7559         }
7560         *arglist.lastp = NULL;
7561
7562         exitstatus = 0;
7563         loopnest++;
7564         flags &= EV_TESTED;
7565         for (sp = arglist.list; sp; sp = sp->next) {
7566                 setvar(n->nfor.var, sp->text, 0);
7567                 evaltree(n->nfor.body, flags);
7568                 if (evalskip) {
7569                         if (evalskip == SKIPCONT && --skipcount <= 0) {
7570                                 evalskip = 0;
7571                                 continue;
7572                         }
7573                         if (evalskip == SKIPBREAK && --skipcount <= 0)
7574                                 evalskip = 0;
7575                         break;
7576                 }
7577         }
7578         loopnest--;
7579  out:
7580         popstackmark(&smark);
7581 }
7582
7583 static void
7584 evalcase(union node *n, int flags)
7585 {
7586         union node *cp;
7587         union node *patp;
7588         struct arglist arglist;
7589         struct stackmark smark;
7590
7591         setstackmark(&smark);
7592         arglist.lastp = &arglist.list;
7593         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7594         exitstatus = 0;
7595         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7596                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7597                         if (casematch(patp, arglist.list->text)) {
7598                                 if (evalskip == 0) {
7599                                         evaltree(cp->nclist.body, flags);
7600                                 }
7601                                 goto out;
7602                         }
7603                 }
7604         }
7605  out:
7606         popstackmark(&smark);
7607 }
7608
7609 /*
7610  * Kick off a subshell to evaluate a tree.
7611  */
7612 static void
7613 evalsubshell(union node *n, int flags)
7614 {
7615         struct job *jp;
7616         int backgnd = (n->type == NBACKGND);
7617         int status;
7618
7619         expredir(n->nredir.redirect);
7620         if (!backgnd && flags & EV_EXIT && !trap[0])
7621                 goto nofork;
7622         INT_OFF;
7623         jp = makejob(n, 1);
7624         if (forkshell(jp, n, backgnd) == 0) {
7625                 INT_ON;
7626                 flags |= EV_EXIT;
7627                 if (backgnd)
7628                         flags &=~ EV_TESTED;
7629  nofork:
7630                 redirect(n->nredir.redirect, 0);
7631                 evaltreenr(n->nredir.n, flags);
7632                 /* never returns */
7633         }
7634         status = 0;
7635         if (! backgnd)
7636                 status = waitforjob(jp);
7637         exitstatus = status;
7638         INT_ON;
7639 }
7640
7641 /*
7642  * Compute the names of the files in a redirection list.
7643  */
7644 static void fixredir(union node *, const char *, int);
7645 static void
7646 expredir(union node *n)
7647 {
7648         union node *redir;
7649
7650         for (redir = n; redir; redir = redir->nfile.next) {
7651                 struct arglist fn;
7652
7653                 memset(&fn, 0, sizeof(fn));
7654                 fn.lastp = &fn.list;
7655                 switch (redir->type) {
7656                 case NFROMTO:
7657                 case NFROM:
7658                 case NTO:
7659                 case NCLOBBER:
7660                 case NAPPEND:
7661                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
7662                         redir->nfile.expfname = fn.list->text;
7663                         break;
7664                 case NFROMFD:
7665                 case NTOFD:
7666                         if (redir->ndup.vname) {
7667                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
7668                                 if (fn.list == NULL)
7669                                         ash_msg_and_raise_error("redir error");
7670                                 fixredir(redir, fn.list->text, 1);
7671                         }
7672                         break;
7673                 }
7674         }
7675 }
7676
7677 /*
7678  * Evaluate a pipeline.  All the processes in the pipeline are children
7679  * of the process creating the pipeline.  (This differs from some versions
7680  * of the shell, which make the last process in a pipeline the parent
7681  * of all the rest.)
7682  */
7683 static void
7684 evalpipe(union node *n, int flags)
7685 {
7686         struct job *jp;
7687         struct nodelist *lp;
7688         int pipelen;
7689         int prevfd;
7690         int pip[2];
7691
7692         TRACE(("evalpipe(0x%lx) called\n", (long)n));
7693         pipelen = 0;
7694         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
7695                 pipelen++;
7696         flags |= EV_EXIT;
7697         INT_OFF;
7698         jp = makejob(n, pipelen);
7699         prevfd = -1;
7700         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7701                 prehash(lp->n);
7702                 pip[1] = -1;
7703                 if (lp->next) {
7704                         if (pipe(pip) < 0) {
7705                                 close(prevfd);
7706                                 ash_msg_and_raise_error("pipe call failed");
7707                         }
7708                 }
7709                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
7710                         INT_ON;
7711                         if (pip[1] >= 0) {
7712                                 close(pip[0]);
7713                         }
7714                         if (prevfd > 0) {
7715                                 dup2(prevfd, 0);
7716                                 close(prevfd);
7717                         }
7718                         if (pip[1] > 1) {
7719                                 dup2(pip[1], 1);
7720                                 close(pip[1]);
7721                         }
7722                         evaltreenr(lp->n, flags);
7723                         /* never returns */
7724                 }
7725                 if (prevfd >= 0)
7726                         close(prevfd);
7727                 prevfd = pip[0];
7728                 close(pip[1]);
7729         }
7730         if (n->npipe.backgnd == 0) {
7731                 exitstatus = waitforjob(jp);
7732                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
7733         }
7734         INT_ON;
7735 }
7736
7737 /*
7738  * Controls whether the shell is interactive or not.
7739  */
7740 static void
7741 setinteractive(int on)
7742 {
7743         static int is_interactive;
7744
7745         if (++on == is_interactive)
7746                 return;
7747         is_interactive = on;
7748         setsignal(SIGINT);
7749         setsignal(SIGQUIT);
7750         setsignal(SIGTERM);
7751 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7752         if (is_interactive > 1) {
7753                 /* Looks like they want an interactive shell */
7754                 static smallint do_banner;
7755
7756                 if (!do_banner) {
7757                         out1fmt(
7758                                 "\n\n"
7759                                 "%s Built-in shell (ash)\n"
7760                                 "Enter 'help' for a list of built-in commands."
7761                                 "\n\n",
7762                                 BB_BANNER);
7763                         do_banner = 1;
7764                 }
7765         }
7766 #endif
7767 }
7768
7769 #if ENABLE_FEATURE_EDITING_VI
7770 #define setvimode(on) do { \
7771         if (on) line_input_state->flags |= VI_MODE; \
7772         else line_input_state->flags &= ~VI_MODE; \
7773 } while (0)
7774 #else
7775 #define setvimode(on) viflag = 0   /* forcibly keep the option off */
7776 #endif
7777
7778 static void
7779 optschanged(void)
7780 {
7781 #if DEBUG
7782         opentrace();
7783 #endif
7784         setinteractive(iflag);
7785         setjobctl(mflag);
7786         setvimode(viflag);
7787 }
7788
7789 static struct localvar *localvars;
7790
7791 /*
7792  * Called after a function returns.
7793  * Interrupts must be off.
7794  */
7795 static void
7796 poplocalvars(void)
7797 {
7798         struct localvar *lvp;
7799         struct var *vp;
7800
7801         while ((lvp = localvars) != NULL) {
7802                 localvars = lvp->next;
7803                 vp = lvp->vp;
7804                 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
7805                 if (vp == NULL) {       /* $- saved */
7806                         memcpy(optlist, lvp->text, sizeof(optlist));
7807                         free((char*)lvp->text);
7808                         optschanged();
7809                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
7810                         unsetvar(vp->text);
7811                 } else {
7812                         if (vp->func)
7813                                 (*vp->func)(strchrnul(lvp->text, '=') + 1);
7814                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
7815                                 free((char*)vp->text);
7816                         vp->flags = lvp->flags;
7817                         vp->text = lvp->text;
7818                 }
7819                 free(lvp);
7820         }
7821 }
7822
7823 static int
7824 evalfun(struct funcnode *func, int argc, char **argv, int flags)
7825 {
7826         volatile struct shparam saveparam;
7827         struct localvar *volatile savelocalvars;
7828         struct jmploc *volatile savehandler;
7829         struct jmploc jmploc;
7830         int e;
7831
7832         saveparam = shellparam;
7833         savelocalvars = localvars;
7834         e = setjmp(jmploc.loc);
7835         if (e) {
7836                 goto funcdone;
7837         }
7838         INT_OFF;
7839         savehandler = exception_handler;
7840         exception_handler = &jmploc;
7841         localvars = NULL;
7842         shellparam.malloc = 0;
7843         func->count++;
7844         funcnest++;
7845         INT_ON;
7846         shellparam.nparam = argc - 1;
7847         shellparam.p = argv + 1;
7848 #if ENABLE_ASH_GETOPTS
7849         shellparam.optind = 1;
7850         shellparam.optoff = -1;
7851 #endif
7852         evaltree(&func->n, flags & EV_TESTED);
7853 funcdone:
7854         INT_OFF;
7855         funcnest--;
7856         freefunc(func);
7857         poplocalvars();
7858         localvars = savelocalvars;
7859         freeparam(&shellparam);
7860         shellparam = saveparam;
7861         exception_handler = savehandler;
7862         INT_ON;
7863         evalskip &= ~SKIPFUNC;
7864         return e;
7865 }
7866
7867 #if ENABLE_ASH_CMDCMD
7868 static char **
7869 parse_command_args(char **argv, const char **path)
7870 {
7871         char *cp, c;
7872
7873         for (;;) {
7874                 cp = *++argv;
7875                 if (!cp)
7876                         return 0;
7877                 if (*cp++ != '-')
7878                         break;
7879                 c = *cp++;
7880                 if (!c)
7881                         break;
7882                 if (c == '-' && !*cp) {
7883                         argv++;
7884                         break;
7885                 }
7886                 do {
7887                         switch (c) {
7888                         case 'p':
7889                                 *path = defpath;
7890                                 break;
7891                         default:
7892                                 /* run 'typecmd' for other options */
7893                                 return 0;
7894                         }
7895                         c = *cp++;
7896                 } while (c);
7897         }
7898         return argv;
7899 }
7900 #endif
7901
7902 /*
7903  * Make a variable a local variable.  When a variable is made local, it's
7904  * value and flags are saved in a localvar structure.  The saved values
7905  * will be restored when the shell function returns.  We handle the name
7906  * "-" as a special case.
7907  */
7908 static void
7909 mklocal(char *name)
7910 {
7911         struct localvar *lvp;
7912         struct var **vpp;
7913         struct var *vp;
7914
7915         INT_OFF;
7916         lvp = ckmalloc(sizeof(struct localvar));
7917         if (LONE_DASH(name)) {
7918                 char *p;
7919                 p = ckmalloc(sizeof(optlist));
7920                 lvp->text = memcpy(p, optlist, sizeof(optlist));
7921                 vp = NULL;
7922         } else {
7923                 char *eq;
7924
7925                 vpp = hashvar(name);
7926                 vp = *findvar(vpp, name);
7927                 eq = strchr(name, '=');
7928                 if (vp == NULL) {
7929                         if (eq)
7930                                 setvareq(name, VSTRFIXED);
7931                         else
7932                                 setvar(name, NULL, VSTRFIXED);
7933                         vp = *vpp;      /* the new variable */
7934                         lvp->flags = VUNSET;
7935                 } else {
7936                         lvp->text = vp->text;
7937                         lvp->flags = vp->flags;
7938                         vp->flags |= VSTRFIXED|VTEXTFIXED;
7939                         if (eq)
7940                                 setvareq(name, 0);
7941                 }
7942         }
7943         lvp->vp = vp;
7944         lvp->next = localvars;
7945         localvars = lvp;
7946         INT_ON;
7947 }
7948
7949 /*
7950  * The "local" command.
7951  */
7952 static int
7953 localcmd(int argc, char **argv)
7954 {
7955         char *name;
7956
7957         argv = argptr;
7958         while ((name = *argv++) != NULL) {
7959                 mklocal(name);
7960         }
7961         return 0;
7962 }
7963
7964 static int
7965 falsecmd(int argc, char **argv)
7966 {
7967         return 1;
7968 }
7969
7970 static int
7971 truecmd(int argc, char **argv)
7972 {
7973         return 0;
7974 }
7975
7976 static int
7977 execcmd(int argc, char **argv)
7978 {
7979         if (argc > 1) {
7980                 iflag = 0;              /* exit on error */
7981                 mflag = 0;
7982                 optschanged();
7983                 shellexec(argv + 1, pathval(), 0);
7984         }
7985         return 0;
7986 }
7987
7988 /*
7989  * The return command.
7990  */
7991 static int
7992 returncmd(int argc, char **argv)
7993 {
7994         /*
7995          * If called outside a function, do what ksh does;
7996          * skip the rest of the file.
7997          */
7998         evalskip = funcnest ? SKIPFUNC : SKIPFILE;
7999         return argv[1] ? number(argv[1]) : exitstatus;
8000 }
8001
8002 /* Forward declarations for builtintab[] */
8003 static int breakcmd(int, char **);
8004 static int dotcmd(int, char **);
8005 static int evalcmd(int, char **);
8006 #if ENABLE_ASH_BUILTIN_ECHO
8007 static int echocmd(int, char **);
8008 #endif
8009 #if ENABLE_ASH_BUILTIN_TEST
8010 static int testcmd(int, char **);
8011 #endif
8012 static int exitcmd(int, char **);
8013 static int exportcmd(int, char **);
8014 #if ENABLE_ASH_GETOPTS
8015 static int getoptscmd(int, char **);
8016 #endif
8017 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8018 static int helpcmd(int argc, char **argv);
8019 #endif
8020 #if ENABLE_ASH_MATH_SUPPORT
8021 static int letcmd(int, char **);
8022 #endif
8023 static int readcmd(int, char **);
8024 static int setcmd(int, char **);
8025 static int shiftcmd(int, char **);
8026 static int timescmd(int, char **);
8027 static int trapcmd(int, char **);
8028 static int umaskcmd(int, char **);
8029 static int unsetcmd(int, char **);
8030 static int ulimitcmd(int, char **);
8031
8032 #define BUILTIN_NOSPEC          "0"
8033 #define BUILTIN_SPECIAL         "1"
8034 #define BUILTIN_REGULAR         "2"
8035 #define BUILTIN_SPEC_REG        "3"
8036 #define BUILTIN_ASSIGN          "4"
8037 #define BUILTIN_SPEC_ASSG       "5"
8038 #define BUILTIN_REG_ASSG        "6"
8039 #define BUILTIN_SPEC_REG_ASSG   "7"
8040
8041 /* make sure to keep these in proper order since it is searched via bsearch() */
8042 static const struct builtincmd builtintab[] = {
8043         { BUILTIN_SPEC_REG      ".", dotcmd },
8044         { BUILTIN_SPEC_REG      ":", truecmd },
8045 #if ENABLE_ASH_BUILTIN_TEST
8046         { BUILTIN_REGULAR       "[", testcmd },
8047         { BUILTIN_REGULAR       "[[", testcmd },
8048 #endif
8049 #if ENABLE_ASH_ALIAS
8050         { BUILTIN_REG_ASSG      "alias", aliascmd },
8051 #endif
8052 #if JOBS
8053         { BUILTIN_REGULAR       "bg", fg_bgcmd },
8054 #endif
8055         { BUILTIN_SPEC_REG      "break", breakcmd },
8056         { BUILTIN_REGULAR       "cd", cdcmd },
8057         { BUILTIN_NOSPEC        "chdir", cdcmd },
8058 #if ENABLE_ASH_CMDCMD
8059         { BUILTIN_REGULAR       "command", commandcmd },
8060 #endif
8061         { BUILTIN_SPEC_REG      "continue", breakcmd },
8062 #if ENABLE_ASH_BUILTIN_ECHO
8063         { BUILTIN_REGULAR       "echo", echocmd },
8064 #endif
8065         { BUILTIN_SPEC_REG      "eval", evalcmd },
8066         { BUILTIN_SPEC_REG      "exec", execcmd },
8067         { BUILTIN_SPEC_REG      "exit", exitcmd },
8068         { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8069         { BUILTIN_REGULAR       "false", falsecmd },
8070 #if JOBS
8071         { BUILTIN_REGULAR       "fg", fg_bgcmd },
8072 #endif
8073 #if ENABLE_ASH_GETOPTS
8074         { BUILTIN_REGULAR       "getopts", getoptscmd },
8075 #endif
8076         { BUILTIN_NOSPEC        "hash", hashcmd },
8077 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8078         { BUILTIN_NOSPEC        "help", helpcmd },
8079 #endif
8080 #if JOBS
8081         { BUILTIN_REGULAR       "jobs", jobscmd },
8082         { BUILTIN_REGULAR       "kill", killcmd },
8083 #endif
8084 #if ENABLE_ASH_MATH_SUPPORT
8085         { BUILTIN_NOSPEC        "let", letcmd },
8086 #endif
8087         { BUILTIN_ASSIGN        "local", localcmd },
8088         { BUILTIN_NOSPEC        "pwd", pwdcmd },
8089         { BUILTIN_REGULAR       "read", readcmd },
8090         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8091         { BUILTIN_SPEC_REG      "return", returncmd },
8092         { BUILTIN_SPEC_REG      "set", setcmd },
8093         { BUILTIN_SPEC_REG      "shift", shiftcmd },
8094         { BUILTIN_SPEC_REG      "source", dotcmd },
8095 #if ENABLE_ASH_BUILTIN_TEST
8096         { BUILTIN_REGULAR       "test", testcmd },
8097 #endif
8098         { BUILTIN_SPEC_REG      "times", timescmd },
8099         { BUILTIN_SPEC_REG      "trap", trapcmd },
8100         { BUILTIN_REGULAR       "true", truecmd },
8101         { BUILTIN_NOSPEC        "type", typecmd },
8102         { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
8103         { BUILTIN_REGULAR       "umask", umaskcmd },
8104 #if ENABLE_ASH_ALIAS
8105         { BUILTIN_REGULAR       "unalias", unaliascmd },
8106 #endif
8107         { BUILTIN_SPEC_REG      "unset", unsetcmd },
8108         { BUILTIN_REGULAR       "wait", waitcmd },
8109 };
8110
8111 #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
8112
8113 #define COMMANDCMD (builtintab + 5 + \
8114         2 * ENABLE_ASH_BUILTIN_TEST + \
8115         ENABLE_ASH_ALIAS + \
8116         ENABLE_ASH_JOB_CONTROL)
8117 #define EXECCMD (builtintab + 7 + \
8118         2 * ENABLE_ASH_BUILTIN_TEST + \
8119         ENABLE_ASH_ALIAS + \
8120         ENABLE_ASH_JOB_CONTROL + \
8121         ENABLE_ASH_CMDCMD + \
8122         ENABLE_ASH_BUILTIN_ECHO)
8123
8124 /*
8125  * Search the table of builtin commands.
8126  */
8127 static struct builtincmd *
8128 find_builtin(const char *name)
8129 {
8130         struct builtincmd *bp;
8131
8132         bp = bsearch(
8133                 name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
8134                 pstrcmp
8135         );
8136         return bp;
8137 }
8138
8139 /*
8140  * Execute a simple command.
8141  */
8142 static int back_exitstatus; /* exit status of backquoted command */
8143 static int
8144 isassignment(const char *p)
8145 {
8146         const char *q = endofname(p);
8147         if (p == q)
8148                 return 0;
8149         return *q == '=';
8150 }
8151 static int
8152 bltincmd(int argc, char **argv)
8153 {
8154         /* Preserve exitstatus of a previous possible redirection
8155          * as POSIX mandates */
8156         return back_exitstatus;
8157 }
8158 static void
8159 evalcommand(union node *cmd, int flags)
8160 {
8161         static const struct builtincmd bltin = {
8162                 "\0\0", bltincmd
8163         };
8164         struct stackmark smark;
8165         union node *argp;
8166         struct arglist arglist;
8167         struct arglist varlist;
8168         char **argv;
8169         int argc;
8170         const struct strlist *sp;
8171         struct cmdentry cmdentry;
8172         struct job *jp;
8173         char *lastarg;
8174         const char *path;
8175         int spclbltin;
8176         int cmd_is_exec;
8177         int status;
8178         char **nargv;
8179         struct builtincmd *bcmd;
8180         int pseudovarflag = 0;
8181
8182         /* First expand the arguments. */
8183         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8184         setstackmark(&smark);
8185         back_exitstatus = 0;
8186
8187         cmdentry.cmdtype = CMDBUILTIN;
8188         cmdentry.u.cmd = &bltin;
8189         varlist.lastp = &varlist.list;
8190         *varlist.lastp = NULL;
8191         arglist.lastp = &arglist.list;
8192         *arglist.lastp = NULL;
8193
8194         argc = 0;
8195         if (cmd->ncmd.args) {
8196                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8197                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8198         }
8199
8200         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8201                 struct strlist **spp;
8202
8203                 spp = arglist.lastp;
8204                 if (pseudovarflag && isassignment(argp->narg.text))
8205                         expandarg(argp, &arglist, EXP_VARTILDE);
8206                 else
8207                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8208
8209                 for (sp = *spp; sp; sp = sp->next)
8210                         argc++;
8211         }
8212
8213         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8214         for (sp = arglist.list; sp; sp = sp->next) {
8215                 TRACE(("evalcommand arg: %s\n", sp->text));
8216                 *nargv++ = sp->text;
8217         }
8218         *nargv = NULL;
8219
8220         lastarg = NULL;
8221         if (iflag && funcnest == 0 && argc > 0)
8222                 lastarg = nargv[-1];
8223
8224         preverrout_fd = 2;
8225         expredir(cmd->ncmd.redirect);
8226         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8227
8228         path = vpath.text;
8229         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8230                 struct strlist **spp;
8231                 char *p;
8232
8233                 spp = varlist.lastp;
8234                 expandarg(argp, &varlist, EXP_VARTILDE);
8235
8236                 /*
8237                  * Modify the command lookup path, if a PATH= assignment
8238                  * is present
8239                  */
8240                 p = (*spp)->text;
8241                 if (varequal(p, path))
8242                         path = p;
8243         }
8244
8245         /* Print the command if xflag is set. */
8246         if (xflag) {
8247                 int n;
8248                 const char *p = " %s";
8249
8250                 p++;
8251                 dprintf(preverrout_fd, p, expandstr(ps4val()));
8252
8253                 sp = varlist.list;
8254                 for (n = 0; n < 2; n++) {
8255                         while (sp) {
8256                                 dprintf(preverrout_fd, p, sp->text);
8257                                 sp = sp->next;
8258                                 if (*p == '%') {
8259                                         p--;
8260                                 }
8261                         }
8262                         sp = arglist.list;
8263                 }
8264                 full_write(preverrout_fd, "\n", 1);
8265         }
8266
8267         cmd_is_exec = 0;
8268         spclbltin = -1;
8269
8270         /* Now locate the command. */
8271         if (argc) {
8272                 const char *oldpath;
8273                 int cmd_flag = DO_ERR;
8274
8275                 path += 5;
8276                 oldpath = path;
8277                 for (;;) {
8278                         find_command(argv[0], &cmdentry, cmd_flag, path);
8279                         if (cmdentry.cmdtype == CMDUNKNOWN) {
8280                                 status = 127;
8281                                 flush_stderr();
8282                                 goto bail;
8283                         }
8284
8285                         /* implement bltin and command here */
8286                         if (cmdentry.cmdtype != CMDBUILTIN)
8287                                 break;
8288                         if (spclbltin < 0)
8289                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8290                         if (cmdentry.u.cmd == EXECCMD)
8291                                 cmd_is_exec++;
8292 #if ENABLE_ASH_CMDCMD
8293                         if (cmdentry.u.cmd == COMMANDCMD) {
8294                                 path = oldpath;
8295                                 nargv = parse_command_args(argv, &path);
8296                                 if (!nargv)
8297                                         break;
8298                                 argc -= nargv - argv;
8299                                 argv = nargv;
8300                                 cmd_flag |= DO_NOFUNC;
8301                         } else
8302 #endif
8303                                 break;
8304                 }
8305         }
8306
8307         if (status) {
8308                 /* We have a redirection error. */
8309                 if (spclbltin > 0)
8310                         raise_exception(EXERROR);
8311  bail:
8312                 exitstatus = status;
8313                 goto out;
8314         }
8315
8316         /* Execute the command. */
8317         switch (cmdentry.cmdtype) {
8318         default:
8319                 /* Fork off a child process if necessary. */
8320                 if (!(flags & EV_EXIT) || trap[0]) {
8321                         INT_OFF;
8322                         jp = makejob(cmd, 1);
8323                         if (forkshell(jp, cmd, FORK_FG) != 0) {
8324                                 exitstatus = waitforjob(jp);
8325                                 INT_ON;
8326                                 break;
8327                         }
8328                         FORCE_INT_ON;
8329                 }
8330                 listsetvar(varlist.list, VEXPORT|VSTACK);
8331                 shellexec(argv, path, cmdentry.u.index);
8332                 /* NOTREACHED */
8333
8334         case CMDBUILTIN:
8335                 cmdenviron = varlist.list;
8336                 if (cmdenviron) {
8337                         struct strlist *list = cmdenviron;
8338                         int i = VNOSET;
8339                         if (spclbltin > 0 || argc == 0) {
8340                                 i = 0;
8341                                 if (cmd_is_exec && argc > 1)
8342                                         i = VEXPORT;
8343                         }
8344                         listsetvar(list, i);
8345                 }
8346                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8347                         int exit_status;
8348                         int i, j;
8349
8350                         i = exception;
8351                         if (i == EXEXIT)
8352                                 goto raise;
8353
8354                         exit_status = 2;
8355                         j = 0;
8356                         if (i == EXINT)
8357                                 j = SIGINT;
8358                         if (i == EXSIG)
8359                                 j = pendingsig;
8360                         if (j)
8361                                 exit_status = j + 128;
8362                         exitstatus = exit_status;
8363
8364                         if (i == EXINT || spclbltin > 0) {
8365  raise:
8366                                 longjmp(exception_handler->loc, 1);
8367                         }
8368                         FORCE_INT_ON;
8369                 }
8370                 break;
8371
8372         case CMDFUNCTION:
8373                 listsetvar(varlist.list, 0);
8374                 if (evalfun(cmdentry.u.func, argc, argv, flags))
8375                         goto raise;
8376                 break;
8377         }
8378
8379  out:
8380         popredir(cmd_is_exec);
8381         if (lastarg)
8382                 /* dsl: I think this is intended to be used to support
8383                  * '_' in 'vi' command mode during line editing...
8384                  * However I implemented that within libedit itself.
8385                  */
8386                 setvar("_", lastarg, 0);
8387         popstackmark(&smark);
8388 }
8389
8390 static int
8391 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8392 {
8393         char *volatile savecmdname;
8394         struct jmploc *volatile savehandler;
8395         struct jmploc jmploc;
8396         int i;
8397
8398         savecmdname = commandname;
8399         i = setjmp(jmploc.loc);
8400         if (i)
8401                 goto cmddone;
8402         savehandler = exception_handler;
8403         exception_handler = &jmploc;
8404         commandname = argv[0];
8405         argptr = argv + 1;
8406         optptr = NULL;                  /* initialize nextopt */
8407         exitstatus = (*cmd->builtin)(argc, argv);
8408         flush_stdout_stderr();
8409  cmddone:
8410         exitstatus |= ferror(stdout);
8411         clearerr(stdout);
8412         commandname = savecmdname;
8413         exsig = 0;
8414         exception_handler = savehandler;
8415
8416         return i;
8417 }
8418
8419 static int
8420 goodname(const char *p)
8421 {
8422         return !*endofname(p);
8423 }
8424
8425
8426 /*
8427  * Search for a command.  This is called before we fork so that the
8428  * location of the command will be available in the parent as well as
8429  * the child.  The check for "goodname" is an overly conservative
8430  * check that the name will not be subject to expansion.
8431  */
8432 static void
8433 prehash(union node *n)
8434 {
8435         struct cmdentry entry;
8436
8437         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8438                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8439 }
8440
8441
8442 /* ============ Builtin commands
8443  *
8444  * Builtin commands whose functions are closely tied to evaluation
8445  * are implemented here.
8446  */
8447
8448 /*
8449  * Handle break and continue commands.  Break, continue, and return are
8450  * all handled by setting the evalskip flag.  The evaluation routines
8451  * above all check this flag, and if it is set they start skipping
8452  * commands rather than executing them.  The variable skipcount is
8453  * the number of loops to break/continue, or the number of function
8454  * levels to return.  (The latter is always 1.)  It should probably
8455  * be an error to break out of more loops than exist, but it isn't
8456  * in the standard shell so we don't make it one here.
8457  */
8458 static int
8459 breakcmd(int argc, char **argv)
8460 {
8461         int n = argc > 1 ? number(argv[1]) : 1;
8462
8463         if (n <= 0)
8464                 ash_msg_and_raise_error(illnum, argv[1]);
8465         if (n > loopnest)
8466                 n = loopnest;
8467         if (n > 0) {
8468                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8469                 skipcount = n;
8470         }
8471         return 0;
8472 }
8473
8474
8475 /* ============ input.c
8476  *
8477  * This implements the input routines used by the parser.
8478  */
8479
8480 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
8481
8482 enum {
8483         INPUT_PUSH_FILE = 1,
8484         INPUT_NOFILE_OK = 2,
8485 };
8486
8487 /*
8488  * NEOF is returned by parsecmd when it encounters an end of file.  It
8489  * must be distinct from NULL, so we use the address of a variable that
8490  * happens to be handy.
8491  */
8492 static int plinno = 1;                  /* input line number */
8493 /* number of characters left in input buffer */
8494 static int parsenleft;                  /* copy of parsefile->nleft */
8495 static int parselleft;                  /* copy of parsefile->lleft */
8496 /* next character in input buffer */
8497 static char *parsenextc;                /* copy of parsefile->nextc */
8498
8499 static int checkkwd;
8500 /* values of checkkwd variable */
8501 #define CHKALIAS        0x1
8502 #define CHKKWD          0x2
8503 #define CHKNL           0x4
8504
8505 static void
8506 popstring(void)
8507 {
8508         struct strpush *sp = parsefile->strpush;
8509
8510         INT_OFF;
8511 #if ENABLE_ASH_ALIAS
8512         if (sp->ap) {
8513                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8514                         checkkwd |= CHKALIAS;
8515                 }
8516                 if (sp->string != sp->ap->val) {
8517                         free(sp->string);
8518                 }
8519                 sp->ap->flag &= ~ALIASINUSE;
8520                 if (sp->ap->flag & ALIASDEAD) {
8521                         unalias(sp->ap->name);
8522                 }
8523         }
8524 #endif
8525         parsenextc = sp->prevstring;
8526         parsenleft = sp->prevnleft;
8527 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8528         parsefile->strpush = sp->prev;
8529         if (sp != &(parsefile->basestrpush))
8530                 free(sp);
8531         INT_ON;
8532 }
8533
8534 static int
8535 preadfd(void)
8536 {
8537         int nr;
8538         char *buf =  parsefile->buf;
8539         parsenextc = buf;
8540
8541  retry:
8542 #if ENABLE_FEATURE_EDITING
8543         if (!iflag || parsefile->fd)
8544                 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8545         else {
8546 #if ENABLE_FEATURE_TAB_COMPLETION
8547                 line_input_state->path_lookup = pathval();
8548 #endif
8549                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8550                 if (nr == 0) {
8551                         /* Ctrl+C pressed */
8552                         if (trap[SIGINT]) {
8553                                 buf[0] = '\n';
8554                                 buf[1] = '\0';
8555                                 raise(SIGINT);
8556                                 return 1;
8557                         }
8558                         goto retry;
8559                 }
8560                 if (nr < 0 && errno == 0) {
8561                         /* Ctrl+D presend */
8562                         nr = 0;
8563                 }
8564         }
8565 #else
8566         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8567 #endif
8568
8569         if (nr < 0) {
8570                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8571                         int flags = fcntl(0, F_GETFL, 0);
8572                         if (flags >= 0 && flags & O_NONBLOCK) {
8573                                 flags &=~ O_NONBLOCK;
8574                                 if (fcntl(0, F_SETFL, flags) >= 0) {
8575                                         out2str("sh: turning off NDELAY mode\n");
8576                                         goto retry;
8577                                 }
8578                         }
8579                 }
8580         }
8581         return nr;
8582 }
8583
8584 /*
8585  * Refill the input buffer and return the next input character:
8586  *
8587  * 1) If a string was pushed back on the input, pop it;
8588  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8589  *    from a string so we can't refill the buffer, return EOF.
8590  * 3) If the is more stuff in this buffer, use it else call read to fill it.
8591  * 4) Process input up to the next newline, deleting nul characters.
8592  */
8593 static int
8594 preadbuffer(void)
8595 {
8596         char *q;
8597         int more;
8598         char savec;
8599
8600         while (parsefile->strpush) {
8601 #if ENABLE_ASH_ALIAS
8602                 if (parsenleft == -1 && parsefile->strpush->ap &&
8603                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8604                         return PEOA;
8605                 }
8606 #endif
8607                 popstring();
8608                 if (--parsenleft >= 0)
8609                         return signed_char2int(*parsenextc++);
8610         }
8611         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8612                 return PEOF;
8613         flush_stdout_stderr();
8614
8615         more = parselleft;
8616         if (more <= 0) {
8617  again:
8618                 more = preadfd();
8619                 if (more <= 0) {
8620                         parselleft = parsenleft = EOF_NLEFT;
8621                         return PEOF;
8622                 }
8623         }
8624
8625         q = parsenextc;
8626
8627         /* delete nul characters */
8628         for (;;) {
8629                 int c;
8630
8631                 more--;
8632                 c = *q;
8633
8634                 if (!c)
8635                         memmove(q, q + 1, more);
8636                 else {
8637                         q++;
8638                         if (c == '\n') {
8639                                 parsenleft = q - parsenextc - 1;
8640                                 break;
8641                         }
8642                 }
8643
8644                 if (more <= 0) {
8645                         parsenleft = q - parsenextc - 1;
8646                         if (parsenleft < 0)
8647                                 goto again;
8648                         break;
8649                 }
8650         }
8651         parselleft = more;
8652
8653         savec = *q;
8654         *q = '\0';
8655
8656         if (vflag) {
8657                 out2str(parsenextc);
8658         }
8659
8660         *q = savec;
8661
8662         return signed_char2int(*parsenextc++);
8663 }
8664
8665 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8666 static int
8667 pgetc(void)
8668 {
8669         return pgetc_as_macro();
8670 }
8671
8672 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8673 #define pgetc_macro() pgetc()
8674 #else
8675 #define pgetc_macro() pgetc_as_macro()
8676 #endif
8677
8678 /*
8679  * Same as pgetc(), but ignores PEOA.
8680  */
8681 #if ENABLE_ASH_ALIAS
8682 static int
8683 pgetc2(void)
8684 {
8685         int c;
8686
8687         do {
8688                 c = pgetc_macro();
8689         } while (c == PEOA);
8690         return c;
8691 }
8692 #else
8693 static int
8694 pgetc2(void)
8695 {
8696         return pgetc_macro();
8697 }
8698 #endif
8699
8700 /*
8701  * Read a line from the script.
8702  */
8703 static char *
8704 pfgets(char *line, int len)
8705 {
8706         char *p = line;
8707         int nleft = len;
8708         int c;
8709
8710         while (--nleft > 0) {
8711                 c = pgetc2();
8712                 if (c == PEOF) {
8713                         if (p == line)
8714                                 return NULL;
8715                         break;
8716                 }
8717                 *p++ = c;
8718                 if (c == '\n')
8719                         break;
8720         }
8721         *p = '\0';
8722         return line;
8723 }
8724
8725 /*
8726  * Undo the last call to pgetc.  Only one character may be pushed back.
8727  * PEOF may be pushed back.
8728  */
8729 static void
8730 pungetc(void)
8731 {
8732         parsenleft++;
8733         parsenextc--;
8734 }
8735
8736 /*
8737  * Push a string back onto the input at this current parsefile level.
8738  * We handle aliases this way.
8739  */
8740 static void
8741 pushstring(char *s, void *ap)
8742 {
8743         struct strpush *sp;
8744         size_t len;
8745
8746         len = strlen(s);
8747         INT_OFF;
8748 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8749         if (parsefile->strpush) {
8750                 sp = ckmalloc(sizeof(struct strpush));
8751                 sp->prev = parsefile->strpush;
8752                 parsefile->strpush = sp;
8753         } else
8754                 sp = parsefile->strpush = &(parsefile->basestrpush);
8755         sp->prevstring = parsenextc;
8756         sp->prevnleft = parsenleft;
8757 #if ENABLE_ASH_ALIAS
8758         sp->ap = (struct alias *)ap;
8759         if (ap) {
8760                 ((struct alias *)ap)->flag |= ALIASINUSE;
8761                 sp->string = s;
8762         }
8763 #endif
8764         parsenextc = s;
8765         parsenleft = len;
8766         INT_ON;
8767 }
8768
8769 /*
8770  * To handle the "." command, a stack of input files is used.  Pushfile
8771  * adds a new entry to the stack and popfile restores the previous level.
8772  */
8773 static void
8774 pushfile(void)
8775 {
8776         struct parsefile *pf;
8777
8778         parsefile->nleft = parsenleft;
8779         parsefile->lleft = parselleft;
8780         parsefile->nextc = parsenextc;
8781         parsefile->linno = plinno;
8782         pf = ckmalloc(sizeof(*pf));
8783         pf->prev = parsefile;
8784         pf->fd = -1;
8785         pf->strpush = NULL;
8786         pf->basestrpush.prev = NULL;
8787         parsefile = pf;
8788 }
8789
8790 static void
8791 popfile(void)
8792 {
8793         struct parsefile *pf = parsefile;
8794
8795         INT_OFF;
8796         if (pf->fd >= 0)
8797                 close(pf->fd);
8798         if (pf->buf)
8799                 free(pf->buf);
8800         while (pf->strpush)
8801                 popstring();
8802         parsefile = pf->prev;
8803         free(pf);
8804         parsenleft = parsefile->nleft;
8805         parselleft = parsefile->lleft;
8806         parsenextc = parsefile->nextc;
8807         plinno = parsefile->linno;
8808         INT_ON;
8809 }
8810
8811 /*
8812  * Return to top level.
8813  */
8814 static void
8815 popallfiles(void)
8816 {
8817         while (parsefile != &basepf)
8818                 popfile();
8819 }
8820
8821 /*
8822  * Close the file(s) that the shell is reading commands from.  Called
8823  * after a fork is done.
8824  */
8825 static void
8826 closescript(void)
8827 {
8828         popallfiles();
8829         if (parsefile->fd > 0) {
8830                 close(parsefile->fd);
8831                 parsefile->fd = 0;
8832         }
8833 }
8834
8835 /*
8836  * Like setinputfile, but takes an open file descriptor.  Call this with
8837  * interrupts off.
8838  */
8839 static void
8840 setinputfd(int fd, int push)
8841 {
8842         fcntl(fd, F_SETFD, FD_CLOEXEC);
8843         if (push) {
8844                 pushfile();
8845                 parsefile->buf = 0;
8846         }
8847         parsefile->fd = fd;
8848         if (parsefile->buf == NULL)
8849                 parsefile->buf = ckmalloc(IBUFSIZ);
8850         parselleft = parsenleft = 0;
8851         plinno = 1;
8852 }
8853
8854 /*
8855  * Set the input to take input from a file.  If push is set, push the
8856  * old input onto the stack first.
8857  */
8858 static int
8859 setinputfile(const char *fname, int flags)
8860 {
8861         int fd;
8862         int fd2;
8863
8864         INT_OFF;
8865         fd = open(fname, O_RDONLY);
8866         if (fd < 0) {
8867                 if (flags & INPUT_NOFILE_OK)
8868                         goto out;
8869                 ash_msg_and_raise_error("can't open %s", fname);
8870         }
8871         if (fd < 10) {
8872                 fd2 = copyfd(fd, 10);
8873                 close(fd);
8874                 if (fd2 < 0)
8875                         ash_msg_and_raise_error("out of file descriptors");
8876                 fd = fd2;
8877         }
8878         setinputfd(fd, flags & INPUT_PUSH_FILE);
8879  out:
8880         INT_ON;
8881         return fd;
8882 }
8883
8884 /*
8885  * Like setinputfile, but takes input from a string.
8886  */
8887 static void
8888 setinputstring(char *string)
8889 {
8890         INT_OFF;
8891         pushfile();
8892         parsenextc = string;
8893         parsenleft = strlen(string);
8894         parsefile->buf = NULL;
8895         plinno = 1;
8896         INT_ON;
8897 }
8898
8899
8900 /* ============ mail.c
8901  *
8902  * Routines to check for mail.
8903  */
8904
8905 #if ENABLE_ASH_MAIL
8906
8907 #define MAXMBOXES 10
8908
8909 /* times of mailboxes */
8910 static time_t mailtime[MAXMBOXES];
8911 /* Set if MAIL or MAILPATH is changed. */
8912 static int mail_var_path_changed;
8913
8914 /*
8915  * Print appropriate message(s) if mail has arrived.
8916  * If mail_var_path_changed is set,
8917  * then the value of MAIL has mail_var_path_changed,
8918  * so we just update the values.
8919  */
8920 static void
8921 chkmail(void)
8922 {
8923         const char *mpath;
8924         char *p;
8925         char *q;
8926         time_t *mtp;
8927         struct stackmark smark;
8928         struct stat statb;
8929
8930         setstackmark(&smark);
8931         mpath = mpathset() ? mpathval() : mailval();
8932         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8933                 p = padvance(&mpath, nullstr);
8934                 if (p == NULL)
8935                         break;
8936                 if (*p == '\0')
8937                         continue;
8938                 for (q = p; *q; q++);
8939 #if DEBUG
8940                 if (q[-1] != '/')
8941                         abort();
8942 #endif
8943                 q[-1] = '\0';                   /* delete trailing '/' */
8944                 if (stat(p, &statb) < 0) {
8945                         *mtp = 0;
8946                         continue;
8947                 }
8948                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8949                         fprintf(
8950                                 stderr, snlfmt,
8951                                 pathopt ? pathopt : "you have mail"
8952                         );
8953                 }
8954                 *mtp = statb.st_mtime;
8955         }
8956         mail_var_path_changed = 0;
8957         popstackmark(&smark);
8958 }
8959
8960 static void
8961 changemail(const char *val)
8962 {
8963         mail_var_path_changed++;
8964 }
8965
8966 #endif /* ASH_MAIL */
8967
8968
8969 /* ============ ??? */
8970
8971 /*
8972  * Set the shell parameters.
8973  */
8974 static void
8975 setparam(char **argv)
8976 {
8977         char **newparam;
8978         char **ap;
8979         int nparam;
8980
8981         for (nparam = 0; argv[nparam]; nparam++);
8982         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8983         while (*argv) {
8984                 *ap++ = ckstrdup(*argv++);
8985         }
8986         *ap = NULL;
8987         freeparam(&shellparam);
8988         shellparam.malloc = 1;
8989         shellparam.nparam = nparam;
8990         shellparam.p = newparam;
8991 #if ENABLE_ASH_GETOPTS
8992         shellparam.optind = 1;
8993         shellparam.optoff = -1;
8994 #endif
8995 }
8996
8997 /*
8998  * Process shell options.  The global variable argptr contains a pointer
8999  * to the argument list; we advance it past the options.
9000  */
9001 static void
9002 minus_o(char *name, int val)
9003 {
9004         int i;
9005
9006         if (name) {
9007                 for (i = 0; i < NOPTS; i++) {
9008                         if (strcmp(name, optnames(i)) == 0) {
9009                                 optlist[i] = val;
9010                                 return;
9011                         }
9012                 }
9013                 ash_msg_and_raise_error("illegal option -o %s", name);
9014         }
9015         out1str("Current option settings\n");
9016         for (i = 0; i < NOPTS; i++)
9017                 out1fmt("%-16s%s\n", optnames(i),
9018                                 optlist[i] ? "on" : "off");
9019 }
9020 static void
9021 setoption(int flag, int val)
9022 {
9023         int i;
9024
9025         for (i = 0; i < NOPTS; i++) {
9026                 if (optletters(i) == flag) {
9027                         optlist[i] = val;
9028                         return;
9029                 }
9030         }
9031         ash_msg_and_raise_error("illegal option -%c", flag);
9032         /* NOTREACHED */
9033 }
9034 static void
9035 options(int cmdline)
9036 {
9037         char *p;
9038         int val;
9039         int c;
9040
9041         if (cmdline)
9042                 minusc = NULL;
9043         while ((p = *argptr) != NULL) {
9044                 argptr++;
9045                 c = *p++;
9046                 if (c == '-') {
9047                         val = 1;
9048                         if (p[0] == '\0' || LONE_DASH(p)) {
9049                                 if (!cmdline) {
9050                                         /* "-" means turn off -x and -v */
9051                                         if (p[0] == '\0')
9052                                                 xflag = vflag = 0;
9053                                         /* "--" means reset params */
9054                                         else if (*argptr == NULL)
9055                                                 setparam(argptr);
9056                                 }
9057                                 break;    /* "-" or  "--" terminates options */
9058                         }
9059                 } else if (c == '+') {
9060                         val = 0;
9061                 } else {
9062                         argptr--;
9063                         break;
9064                 }
9065                 while ((c = *p++) != '\0') {
9066                         if (c == 'c' && cmdline) {
9067                                 minusc = p;     /* command is after shell args*/
9068                         } else if (c == 'o') {
9069                                 minus_o(*argptr, val);
9070                                 if (*argptr)
9071                                         argptr++;
9072                         } else if (cmdline && (c == '-')) {     // long options
9073                                 if (strcmp(p, "login") == 0)
9074                                         isloginsh = 1;
9075                                 break;
9076                         } else {
9077                                 setoption(c, val);
9078                         }
9079                 }
9080         }
9081 }
9082
9083 /*
9084  * The shift builtin command.
9085  */
9086 static int
9087 shiftcmd(int argc, char **argv)
9088 {
9089         int n;
9090         char **ap1, **ap2;
9091
9092         n = 1;
9093         if (argc > 1)
9094                 n = number(argv[1]);
9095         if (n > shellparam.nparam)
9096                 ash_msg_and_raise_error("can't shift that many");
9097         INT_OFF;
9098         shellparam.nparam -= n;
9099         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9100                 if (shellparam.malloc)
9101                         free(*ap1);
9102         }
9103         ap2 = shellparam.p;
9104         while ((*ap2++ = *ap1++) != NULL);
9105 #if ENABLE_ASH_GETOPTS
9106         shellparam.optind = 1;
9107         shellparam.optoff = -1;
9108 #endif
9109         INT_ON;
9110         return 0;
9111 }
9112
9113 /*
9114  * POSIX requires that 'set' (but not export or readonly) output the
9115  * variables in lexicographic order - by the locale's collating order (sigh).
9116  * Maybe we could keep them in an ordered balanced binary tree
9117  * instead of hashed lists.
9118  * For now just roll 'em through qsort for printing...
9119  */
9120 static int
9121 showvars(const char *sep_prefix, int on, int off)
9122 {
9123         const char *sep;
9124         char **ep, **epend;
9125
9126         ep = listvars(on, off, &epend);
9127         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9128
9129         sep = *sep_prefix ? " " : sep_prefix;
9130
9131         for (; ep < epend; ep++) {
9132                 const char *p;
9133                 const char *q;
9134
9135                 p = strchrnul(*ep, '=');
9136                 q = nullstr;
9137                 if (*p)
9138                         q = single_quote(++p);
9139                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9140         }
9141         return 0;
9142 }
9143
9144 /*
9145  * The set command builtin.
9146  */
9147 static int
9148 setcmd(int argc, char **argv)
9149 {
9150         if (argc == 1)
9151                 return showvars(nullstr, 0, VUNSET);
9152         INT_OFF;
9153         options(0);
9154         optschanged();
9155         if (*argptr != NULL) {
9156                 setparam(argptr);
9157         }
9158         INT_ON;
9159         return 0;
9160 }
9161
9162 #if ENABLE_ASH_RANDOM_SUPPORT
9163 /* Roughly copied from bash.. */
9164 static void
9165 change_random(const char *value)
9166 {
9167         if (value == NULL) {
9168                 /* "get", generate */
9169                 char buf[16];
9170
9171                 rseed = rseed * 1103515245 + 12345;
9172                 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9173                 /* set without recursion */
9174                 setvar(vrandom.text, buf, VNOFUNC);
9175                 vrandom.flags &= ~VNOFUNC;
9176         } else {
9177                 /* set/reset */
9178                 rseed = strtoul(value, (char **)NULL, 10);
9179         }
9180 }
9181 #endif
9182
9183 #if ENABLE_ASH_GETOPTS
9184 static int
9185 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9186 {
9187         char *p, *q;
9188         char c = '?';
9189         int done = 0;
9190         int err = 0;
9191         char s[12];
9192         char **optnext;
9193
9194         if (*param_optind < 1)
9195                 return 1;
9196         optnext = optfirst + *param_optind - 1;
9197
9198         if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9199                 p = NULL;
9200         else
9201                 p = optnext[-1] + *optoff;
9202         if (p == NULL || *p == '\0') {
9203                 /* Current word is done, advance */
9204                 p = *optnext;
9205                 if (p == NULL || *p != '-' || *++p == '\0') {
9206  atend:
9207                         p = NULL;
9208                         done = 1;
9209                         goto out;
9210                 }
9211                 optnext++;
9212                 if (LONE_DASH(p))        /* check for "--" */
9213                         goto atend;
9214         }
9215
9216         c = *p++;
9217         for (q = optstr; *q != c; ) {
9218                 if (*q == '\0') {
9219                         if (optstr[0] == ':') {
9220                                 s[0] = c;
9221                                 s[1] = '\0';
9222                                 err |= setvarsafe("OPTARG", s, 0);
9223                         } else {
9224                                 fprintf(stderr, "Illegal option -%c\n", c);
9225                                 unsetvar("OPTARG");
9226                         }
9227                         c = '?';
9228                         goto out;
9229                 }
9230                 if (*++q == ':')
9231                         q++;
9232         }
9233
9234         if (*++q == ':') {
9235                 if (*p == '\0' && (p = *optnext) == NULL) {
9236                         if (optstr[0] == ':') {
9237                                 s[0] = c;
9238                                 s[1] = '\0';
9239                                 err |= setvarsafe("OPTARG", s, 0);
9240                                 c = ':';
9241                         } else {
9242                                 fprintf(stderr, "No arg for -%c option\n", c);
9243                                 unsetvar("OPTARG");
9244                                 c = '?';
9245                         }
9246                         goto out;
9247                 }
9248
9249                 if (p == *optnext)
9250                         optnext++;
9251                 err |= setvarsafe("OPTARG", p, 0);
9252                 p = NULL;
9253         } else
9254                 err |= setvarsafe("OPTARG", nullstr, 0);
9255  out:
9256         *optoff = p ? p - *(optnext - 1) : -1;
9257         *param_optind = optnext - optfirst + 1;
9258         fmtstr(s, sizeof(s), "%d", *param_optind);
9259         err |= setvarsafe("OPTIND", s, VNOFUNC);
9260         s[0] = c;
9261         s[1] = '\0';
9262         err |= setvarsafe(optvar, s, 0);
9263         if (err) {
9264                 *param_optind = 1;
9265                 *optoff = -1;
9266                 flush_stdout_stderr();
9267                 raise_exception(EXERROR);
9268         }
9269         return done;
9270 }
9271
9272 /*
9273  * The getopts builtin.  Shellparam.optnext points to the next argument
9274  * to be processed.  Shellparam.optptr points to the next character to
9275  * be processed in the current argument.  If shellparam.optnext is NULL,
9276  * then it's the first time getopts has been called.
9277  */
9278 static int
9279 getoptscmd(int argc, char **argv)
9280 {
9281         char **optbase;
9282
9283         if (argc < 3)
9284                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9285         if (argc == 3) {
9286                 optbase = shellparam.p;
9287                 if (shellparam.optind > shellparam.nparam + 1) {
9288                         shellparam.optind = 1;
9289                         shellparam.optoff = -1;
9290                 }
9291         } else {
9292                 optbase = &argv[3];
9293                 if (shellparam.optind > argc - 2) {
9294                         shellparam.optind = 1;
9295                         shellparam.optoff = -1;
9296                 }
9297         }
9298
9299         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9300                         &shellparam.optoff);
9301 }
9302 #endif /* ASH_GETOPTS */
9303
9304
9305 /* ============ Shell parser */
9306
9307 static int tokpushback;                /* last token pushed back */
9308 #define NEOF ((union node *)&tokpushback)
9309 static int parsebackquote;             /* nonzero if we are inside backquotes */
9310 static int lasttoken;                  /* last token read */
9311 static char *wordtext;                 /* text of last word returned by readtoken */
9312 static struct nodelist *backquotelist;
9313 static union node *redirnode;
9314 static struct heredoc *heredoc;
9315 static int quoteflag;                  /* set if (part of) last token was quoted */
9316
9317 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9318 static void
9319 raise_error_syntax(const char *msg)
9320 {
9321         ash_msg_and_raise_error("syntax error: %s", msg);
9322         /* NOTREACHED */
9323 }
9324
9325 /*
9326  * Called when an unexpected token is read during the parse.  The argument
9327  * is the token that is expected, or -1 if more than one type of token can
9328  * occur at this point.
9329  */
9330 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9331 static void
9332 raise_error_unexpected_syntax(int token)
9333 {
9334         char msg[64];
9335         int l;
9336
9337         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9338         if (token >= 0)
9339                 sprintf(msg + l, " (expecting %s)", tokname(token));
9340         raise_error_syntax(msg);
9341         /* NOTREACHED */
9342 }
9343
9344 #define EOFMARKLEN 79
9345
9346 struct heredoc {
9347         struct heredoc *next;   /* next here document in list */
9348         union node *here;               /* redirection node */
9349         char *eofmark;          /* string indicating end of input */
9350         int striptabs;          /* if set, strip leading tabs */
9351 };
9352
9353 static struct heredoc *heredoclist;    /* list of here documents to read */
9354
9355 /* parsing is heavily cross-recursive, need these forward decls */
9356 static union node *andor(void);
9357 static union node *pipeline(void);
9358 static union node *parse_command(void);
9359 static void parseheredoc(void);
9360 static char peektoken(void);
9361 static int readtoken(void);
9362
9363 static union node *
9364 list(int nlflag)
9365 {
9366         union node *n1, *n2, *n3;
9367         int tok;
9368
9369         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9370         if (nlflag == 2 && peektoken())
9371                 return NULL;
9372         n1 = NULL;
9373         for (;;) {
9374                 n2 = andor();
9375                 tok = readtoken();
9376                 if (tok == TBACKGND) {
9377                         if (n2->type == NPIPE) {
9378                                 n2->npipe.backgnd = 1;
9379                         } else {
9380                                 if (n2->type != NREDIR) {
9381                                         n3 = stalloc(sizeof(struct nredir));
9382                                         n3->nredir.n = n2;
9383                                         n3->nredir.redirect = NULL;
9384                                         n2 = n3;
9385                                 }
9386                                 n2->type = NBACKGND;
9387                         }
9388                 }
9389                 if (n1 == NULL) {
9390                         n1 = n2;
9391                 } else {
9392                         n3 = stalloc(sizeof(struct nbinary));
9393                         n3->type = NSEMI;
9394                         n3->nbinary.ch1 = n1;
9395                         n3->nbinary.ch2 = n2;
9396                         n1 = n3;
9397                 }
9398                 switch (tok) {
9399                 case TBACKGND:
9400                 case TSEMI:
9401                         tok = readtoken();
9402                         /* fall through */
9403                 case TNL:
9404                         if (tok == TNL) {
9405                                 parseheredoc();
9406                                 if (nlflag == 1)
9407                                         return n1;
9408                         } else {
9409                                 tokpushback++;
9410                         }
9411                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9412                         if (peektoken())
9413                                 return n1;
9414                         break;
9415                 case TEOF:
9416                         if (heredoclist)
9417                                 parseheredoc();
9418                         else
9419                                 pungetc();              /* push back EOF on input */
9420                         return n1;
9421                 default:
9422                         if (nlflag == 1)
9423                                 raise_error_unexpected_syntax(-1);
9424                         tokpushback++;
9425                         return n1;
9426                 }
9427         }
9428 }
9429
9430 static union node *
9431 andor(void)
9432 {
9433         union node *n1, *n2, *n3;
9434         int t;
9435
9436         n1 = pipeline();
9437         for (;;) {
9438                 t = readtoken();
9439                 if (t == TAND) {
9440                         t = NAND;
9441                 } else if (t == TOR) {
9442                         t = NOR;
9443                 } else {
9444                         tokpushback++;
9445                         return n1;
9446                 }
9447                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9448                 n2 = pipeline();
9449                 n3 = stalloc(sizeof(struct nbinary));
9450                 n3->type = t;
9451                 n3->nbinary.ch1 = n1;
9452                 n3->nbinary.ch2 = n2;
9453                 n1 = n3;
9454         }
9455 }
9456
9457 static union node *
9458 pipeline(void)
9459 {
9460         union node *n1, *n2, *pipenode;
9461         struct nodelist *lp, *prev;
9462         int negate;
9463
9464         negate = 0;
9465         TRACE(("pipeline: entered\n"));
9466         if (readtoken() == TNOT) {
9467                 negate = !negate;
9468                 checkkwd = CHKKWD | CHKALIAS;
9469         } else
9470                 tokpushback++;
9471         n1 = parse_command();
9472         if (readtoken() == TPIPE) {
9473                 pipenode = stalloc(sizeof(struct npipe));
9474                 pipenode->type = NPIPE;
9475                 pipenode->npipe.backgnd = 0;
9476                 lp = stalloc(sizeof(struct nodelist));
9477                 pipenode->npipe.cmdlist = lp;
9478                 lp->n = n1;
9479                 do {
9480                         prev = lp;
9481                         lp = stalloc(sizeof(struct nodelist));
9482                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9483                         lp->n = parse_command();
9484                         prev->next = lp;
9485                 } while (readtoken() == TPIPE);
9486                 lp->next = NULL;
9487                 n1 = pipenode;
9488         }
9489         tokpushback++;
9490         if (negate) {
9491                 n2 = stalloc(sizeof(struct nnot));
9492                 n2->type = NNOT;
9493                 n2->nnot.com = n1;
9494                 return n2;
9495         }
9496         return n1;
9497 }
9498
9499 static union node *
9500 makename(void)
9501 {
9502         union node *n;
9503
9504         n = stalloc(sizeof(struct narg));
9505         n->type = NARG;
9506         n->narg.next = NULL;
9507         n->narg.text = wordtext;
9508         n->narg.backquote = backquotelist;
9509         return n;
9510 }
9511
9512 static void
9513 fixredir(union node *n, const char *text, int err)
9514 {
9515         TRACE(("Fix redir %s %d\n", text, err));
9516         if (!err)
9517                 n->ndup.vname = NULL;
9518
9519         if (isdigit(text[0]) && text[1] == '\0')
9520                 n->ndup.dupfd = text[0] - '0';
9521         else if (LONE_DASH(text))
9522                 n->ndup.dupfd = -1;
9523         else {
9524                 if (err)
9525                         raise_error_syntax("Bad fd number");
9526                 n->ndup.vname = makename();
9527         }
9528 }
9529
9530 /*
9531  * Returns true if the text contains nothing to expand (no dollar signs
9532  * or backquotes).
9533  */
9534 static int
9535 noexpand(char *text)
9536 {
9537         char *p;
9538         char c;
9539
9540         p = text;
9541         while ((c = *p++) != '\0') {
9542                 if (c == CTLQUOTEMARK)
9543                         continue;
9544                 if (c == CTLESC)
9545                         p++;
9546                 else if (SIT(c, BASESYNTAX) == CCTL)
9547                         return 0;
9548         }
9549         return 1;
9550 }
9551
9552 static void
9553 parsefname(void)
9554 {
9555         union node *n = redirnode;
9556
9557         if (readtoken() != TWORD)
9558                 raise_error_unexpected_syntax(-1);
9559         if (n->type == NHERE) {
9560                 struct heredoc *here = heredoc;
9561                 struct heredoc *p;
9562                 int i;
9563
9564                 if (quoteflag == 0)
9565                         n->type = NXHERE;
9566                 TRACE(("Here document %d\n", n->type));
9567                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9568                         raise_error_syntax("Illegal eof marker for << redirection");
9569                 rmescapes(wordtext);
9570                 here->eofmark = wordtext;
9571                 here->next = NULL;
9572                 if (heredoclist == NULL)
9573                         heredoclist = here;
9574                 else {
9575                         for (p = heredoclist; p->next; p = p->next);
9576                         p->next = here;
9577                 }
9578         } else if (n->type == NTOFD || n->type == NFROMFD) {
9579                 fixredir(n, wordtext, 0);
9580         } else {
9581                 n->nfile.fname = makename();
9582         }
9583 }
9584
9585 static union node *
9586 simplecmd(void)
9587 {
9588         union node *args, **app;
9589         union node *n = NULL;
9590         union node *vars, **vpp;
9591         union node **rpp, *redir;
9592         int savecheckkwd;
9593
9594         args = NULL;
9595         app = &args;
9596         vars = NULL;
9597         vpp = &vars;
9598         redir = NULL;
9599         rpp = &redir;
9600
9601         savecheckkwd = CHKALIAS;
9602         for (;;) {
9603                 checkkwd = savecheckkwd;
9604                 switch (readtoken()) {
9605                 case TWORD:
9606                         n = stalloc(sizeof(struct narg));
9607                         n->type = NARG;
9608                         n->narg.text = wordtext;
9609                         n->narg.backquote = backquotelist;
9610                         if (savecheckkwd && isassignment(wordtext)) {
9611                                 *vpp = n;
9612                                 vpp = &n->narg.next;
9613                         } else {
9614                                 *app = n;
9615                                 app = &n->narg.next;
9616                                 savecheckkwd = 0;
9617                         }
9618                         break;
9619                 case TREDIR:
9620                         *rpp = n = redirnode;
9621                         rpp = &n->nfile.next;
9622                         parsefname();   /* read name of redirection file */
9623                         break;
9624                 case TLP:
9625                         if (args && app == &args->narg.next
9626                          && !vars && !redir
9627                         ) {
9628                                 struct builtincmd *bcmd;
9629                                 const char *name;
9630
9631                                 /* We have a function */
9632                                 if (readtoken() != TRP)
9633                                         raise_error_unexpected_syntax(TRP);
9634                                 name = n->narg.text;
9635                                 if (!goodname(name)
9636                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9637                                 ) {
9638                                         raise_error_syntax("Bad function name");
9639                                 }
9640                                 n->type = NDEFUN;
9641                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9642                                 n->narg.next = parse_command();
9643                                 return n;
9644                         }
9645                         /* fall through */
9646                 default:
9647                         tokpushback++;
9648                         goto out;
9649                 }
9650         }
9651  out:
9652         *app = NULL;
9653         *vpp = NULL;
9654         *rpp = NULL;
9655         n = stalloc(sizeof(struct ncmd));
9656         n->type = NCMD;
9657         n->ncmd.args = args;
9658         n->ncmd.assign = vars;
9659         n->ncmd.redirect = redir;
9660         return n;
9661 }
9662
9663 static union node *
9664 parse_command(void)
9665 {
9666         union node *n1, *n2;
9667         union node *ap, **app;
9668         union node *cp, **cpp;
9669         union node *redir, **rpp;
9670         union node **rpp2;
9671         int t;
9672
9673         redir = NULL;
9674         rpp2 = &redir;
9675
9676         switch (readtoken()) {
9677         default:
9678                 raise_error_unexpected_syntax(-1);
9679                 /* NOTREACHED */
9680         case TIF:
9681                 n1 = stalloc(sizeof(struct nif));
9682                 n1->type = NIF;
9683                 n1->nif.test = list(0);
9684                 if (readtoken() != TTHEN)
9685                         raise_error_unexpected_syntax(TTHEN);
9686                 n1->nif.ifpart = list(0);
9687                 n2 = n1;
9688                 while (readtoken() == TELIF) {
9689                         n2->nif.elsepart = stalloc(sizeof(struct nif));
9690                         n2 = n2->nif.elsepart;
9691                         n2->type = NIF;
9692                         n2->nif.test = list(0);
9693                         if (readtoken() != TTHEN)
9694                                 raise_error_unexpected_syntax(TTHEN);
9695                         n2->nif.ifpart = list(0);
9696                 }
9697                 if (lasttoken == TELSE)
9698                         n2->nif.elsepart = list(0);
9699                 else {
9700                         n2->nif.elsepart = NULL;
9701                         tokpushback++;
9702                 }
9703                 t = TFI;
9704                 break;
9705         case TWHILE:
9706         case TUNTIL: {
9707                 int got;
9708                 n1 = stalloc(sizeof(struct nbinary));
9709                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9710                 n1->nbinary.ch1 = list(0);
9711                 got = readtoken();
9712                 if (got != TDO) {
9713                         TRACE(("expecting DO got %s %s\n", tokname(got),
9714                                         got == TWORD ? wordtext : ""));
9715                         raise_error_unexpected_syntax(TDO);
9716                 }
9717                 n1->nbinary.ch2 = list(0);
9718                 t = TDONE;
9719                 break;
9720         }
9721         case TFOR:
9722                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9723                         raise_error_syntax("Bad for loop variable");
9724                 n1 = stalloc(sizeof(struct nfor));
9725                 n1->type = NFOR;
9726                 n1->nfor.var = wordtext;
9727                 checkkwd = CHKKWD | CHKALIAS;
9728                 if (readtoken() == TIN) {
9729                         app = &ap;
9730                         while (readtoken() == TWORD) {
9731                                 n2 = stalloc(sizeof(struct narg));
9732                                 n2->type = NARG;
9733                                 n2->narg.text = wordtext;
9734                                 n2->narg.backquote = backquotelist;
9735                                 *app = n2;
9736                                 app = &n2->narg.next;
9737                         }
9738                         *app = NULL;
9739                         n1->nfor.args = ap;
9740                         if (lasttoken != TNL && lasttoken != TSEMI)
9741                                 raise_error_unexpected_syntax(-1);
9742                 } else {
9743                         n2 = stalloc(sizeof(struct narg));
9744                         n2->type = NARG;
9745                         n2->narg.text = (char *)dolatstr;
9746                         n2->narg.backquote = NULL;
9747                         n2->narg.next = NULL;
9748                         n1->nfor.args = n2;
9749                         /*
9750                          * Newline or semicolon here is optional (but note
9751                          * that the original Bourne shell only allowed NL).
9752                          */
9753                         if (lasttoken != TNL && lasttoken != TSEMI)
9754                                 tokpushback++;
9755                 }
9756                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9757                 if (readtoken() != TDO)
9758                         raise_error_unexpected_syntax(TDO);
9759                 n1->nfor.body = list(0);
9760                 t = TDONE;
9761                 break;
9762         case TCASE:
9763                 n1 = stalloc(sizeof(struct ncase));
9764                 n1->type = NCASE;
9765                 if (readtoken() != TWORD)
9766                         raise_error_unexpected_syntax(TWORD);
9767                 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9768                 n2->type = NARG;
9769                 n2->narg.text = wordtext;
9770                 n2->narg.backquote = backquotelist;
9771                 n2->narg.next = NULL;
9772                 do {
9773                         checkkwd = CHKKWD | CHKALIAS;
9774                 } while (readtoken() == TNL);
9775                 if (lasttoken != TIN)
9776                         raise_error_unexpected_syntax(TIN);
9777                 cpp = &n1->ncase.cases;
9778  next_case:
9779                 checkkwd = CHKNL | CHKKWD;
9780                 t = readtoken();
9781                 while (t != TESAC) {
9782                         if (lasttoken == TLP)
9783                                 readtoken();
9784                         *cpp = cp = stalloc(sizeof(struct nclist));
9785                         cp->type = NCLIST;
9786                         app = &cp->nclist.pattern;
9787                         for (;;) {
9788                                 *app = ap = stalloc(sizeof(struct narg));
9789                                 ap->type = NARG;
9790                                 ap->narg.text = wordtext;
9791                                 ap->narg.backquote = backquotelist;
9792                                 if (readtoken() != TPIPE)
9793                                         break;
9794                                 app = &ap->narg.next;
9795                                 readtoken();
9796                         }
9797                         ap->narg.next = NULL;
9798                         if (lasttoken != TRP)
9799                                 raise_error_unexpected_syntax(TRP);
9800                         cp->nclist.body = list(2);
9801
9802                         cpp = &cp->nclist.next;
9803
9804                         checkkwd = CHKNL | CHKKWD;
9805                         t = readtoken();
9806                         if (t != TESAC) {
9807                                 if (t != TENDCASE)
9808                                         raise_error_unexpected_syntax(TENDCASE);
9809                                 goto next_case;
9810                         }
9811                 }
9812                 *cpp = NULL;
9813                 goto redir;
9814         case TLP:
9815                 n1 = stalloc(sizeof(struct nredir));
9816                 n1->type = NSUBSHELL;
9817                 n1->nredir.n = list(0);
9818                 n1->nredir.redirect = NULL;
9819                 t = TRP;
9820                 break;
9821         case TBEGIN:
9822                 n1 = list(0);
9823                 t = TEND;
9824                 break;
9825         case TWORD:
9826         case TREDIR:
9827                 tokpushback++;
9828                 return simplecmd();
9829         }
9830
9831         if (readtoken() != t)
9832                 raise_error_unexpected_syntax(t);
9833
9834  redir:
9835         /* Now check for redirection which may follow command */
9836         checkkwd = CHKKWD | CHKALIAS;
9837         rpp = rpp2;
9838         while (readtoken() == TREDIR) {
9839                 *rpp = n2 = redirnode;
9840                 rpp = &n2->nfile.next;
9841                 parsefname();
9842         }
9843         tokpushback++;
9844         *rpp = NULL;
9845         if (redir) {
9846                 if (n1->type != NSUBSHELL) {
9847                         n2 = stalloc(sizeof(struct nredir));
9848                         n2->type = NREDIR;
9849                         n2->nredir.n = n1;
9850                         n1 = n2;
9851                 }
9852                 n1->nredir.redirect = redir;
9853         }
9854         return n1;
9855 }
9856
9857 /*
9858  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
9859  * is not NULL, read a here document.  In the latter case, eofmark is the
9860  * word which marks the end of the document and striptabs is true if
9861  * leading tabs should be stripped from the document.  The argument firstc
9862  * is the first character of the input token or document.
9863  *
9864  * Because C does not have internal subroutines, I have simulated them
9865  * using goto's to implement the subroutine linkage.  The following macros
9866  * will run code that appears at the end of readtoken1.
9867  */
9868
9869 static int parsebackquote;             /* nonzero if we are inside backquotes */
9870
9871 #define CHECKEND()      {goto checkend; checkend_return:;}
9872 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
9873 #define PARSESUB()      {goto parsesub; parsesub_return:;}
9874 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9875 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9876 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
9877
9878 static int
9879 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9880 {
9881         int c = firstc;
9882         char *out;
9883         int len;
9884         char line[EOFMARKLEN + 1];
9885         struct nodelist *bqlist = 0;
9886         int quotef = 0;
9887         int dblquote = 0;
9888         int varnest = 0;    /* levels of variables expansion */
9889         int arinest = 0;    /* levels of arithmetic expansion */
9890         int parenlevel = 0; /* levels of parens in arithmetic */
9891         int dqvarnest = 0;  /* levels of variables expansion within double quotes */
9892         int oldstyle = 0;
9893         int prevsyntax = 0; /* syntax before arithmetic */
9894 #if __GNUC__
9895         /* Avoid longjmp clobbering */
9896         (void) &out;
9897         (void) &quotef;
9898         (void) &dblquote;
9899         (void) &varnest;
9900         (void) &arinest;
9901         (void) &parenlevel;
9902         (void) &dqvarnest;
9903         (void) &oldstyle;
9904         (void) &prevsyntax;
9905         (void) &syntax;
9906 #endif
9907
9908         startlinno = plinno;
9909         dblquote = 0;
9910         if (syntax == DQSYNTAX)
9911                 dblquote = 1;
9912         quotef = 0;
9913         bqlist = NULL;
9914         varnest = 0;
9915         arinest = 0;
9916         parenlevel = 0;
9917         dqvarnest = 0;
9918
9919         STARTSTACKSTR(out);
9920         loop: { /* for each line, until end of word */
9921                 CHECKEND();     /* set c to PEOF if at end of here document */
9922                 for (;;) {      /* until end of line or end of word */
9923                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
9924                         switch (SIT(c, syntax)) {
9925                         case CNL:       /* '\n' */
9926                                 if (syntax == BASESYNTAX)
9927                                         goto endword;   /* exit outer loop */
9928                                 USTPUTC(c, out);
9929                                 plinno++;
9930                                 if (doprompt)
9931                                         setprompt(2);
9932                                 c = pgetc();
9933                                 goto loop;              /* continue outer loop */
9934                         case CWORD:
9935                                 USTPUTC(c, out);
9936                                 break;
9937                         case CCTL:
9938                                 if (eofmark == NULL || dblquote)
9939                                         USTPUTC(CTLESC, out);
9940                                 USTPUTC(c, out);
9941                                 break;
9942                         case CBACK:     /* backslash */
9943                                 c = pgetc2();
9944                                 if (c == PEOF) {
9945                                         USTPUTC(CTLESC, out);
9946                                         USTPUTC('\\', out);
9947                                         pungetc();
9948                                 } else if (c == '\n') {
9949                                         if (doprompt)
9950                                                 setprompt(2);
9951                                 } else {
9952                                         if (dblquote &&
9953                                                 c != '\\' && c != '`' &&
9954                                                 c != '$' && (
9955                                                         c != '"' ||
9956                                                         eofmark != NULL)
9957                                         ) {
9958                                                 USTPUTC(CTLESC, out);
9959                                                 USTPUTC('\\', out);
9960                                         }
9961                                         if (SIT(c, SQSYNTAX) == CCTL)
9962                                                 USTPUTC(CTLESC, out);
9963                                         USTPUTC(c, out);
9964                                         quotef++;
9965                                 }
9966                                 break;
9967                         case CSQUOTE:
9968                                 syntax = SQSYNTAX;
9969  quotemark:
9970                                 if (eofmark == NULL) {
9971                                         USTPUTC(CTLQUOTEMARK, out);
9972                                 }
9973                                 break;
9974                         case CDQUOTE:
9975                                 syntax = DQSYNTAX;
9976                                 dblquote = 1;
9977                                 goto quotemark;
9978                         case CENDQUOTE:
9979                                 if (eofmark != NULL && arinest == 0
9980                                  && varnest == 0
9981                                 ) {
9982                                         USTPUTC(c, out);
9983                                 } else {
9984                                         if (dqvarnest == 0) {
9985                                                 syntax = BASESYNTAX;
9986                                                 dblquote = 0;
9987                                         }
9988                                         quotef++;
9989                                         goto quotemark;
9990                                 }
9991                                 break;
9992                         case CVAR:      /* '$' */
9993                                 PARSESUB();             /* parse substitution */
9994                                 break;
9995                         case CENDVAR:   /* '}' */
9996                                 if (varnest > 0) {
9997                                         varnest--;
9998                                         if (dqvarnest > 0) {
9999                                                 dqvarnest--;
10000                                         }
10001                                         USTPUTC(CTLENDVAR, out);
10002                                 } else {
10003                                         USTPUTC(c, out);
10004                                 }
10005                                 break;
10006 #if ENABLE_ASH_MATH_SUPPORT
10007                         case CLP:       /* '(' in arithmetic */
10008                                 parenlevel++;
10009                                 USTPUTC(c, out);
10010                                 break;
10011                         case CRP:       /* ')' in arithmetic */
10012                                 if (parenlevel > 0) {
10013                                         USTPUTC(c, out);
10014                                         --parenlevel;
10015                                 } else {
10016                                         if (pgetc() == ')') {
10017                                                 if (--arinest == 0) {
10018                                                         USTPUTC(CTLENDARI, out);
10019                                                         syntax = prevsyntax;
10020                                                         if (syntax == DQSYNTAX)
10021                                                                 dblquote = 1;
10022                                                         else
10023                                                                 dblquote = 0;
10024                                                 } else
10025                                                         USTPUTC(')', out);
10026                                         } else {
10027                                                 /*
10028                                                  * unbalanced parens
10029                                                  *  (don't 2nd guess - no error)
10030                                                  */
10031                                                 pungetc();
10032                                                 USTPUTC(')', out);
10033                                         }
10034                                 }
10035                                 break;
10036 #endif
10037                         case CBQUOTE:   /* '`' */
10038                                 PARSEBACKQOLD();
10039                                 break;
10040                         case CENDFILE:
10041                                 goto endword;           /* exit outer loop */
10042                         case CIGN:
10043                                 break;
10044                         default:
10045                                 if (varnest == 0)
10046                                         goto endword;   /* exit outer loop */
10047 #if ENABLE_ASH_ALIAS
10048                                 if (c != PEOA)
10049 #endif
10050                                         USTPUTC(c, out);
10051
10052                         }
10053                         c = pgetc_macro();
10054                 }
10055         }
10056  endword:
10057 #if ENABLE_ASH_MATH_SUPPORT
10058         if (syntax == ARISYNTAX)
10059                 raise_error_syntax("Missing '))'");
10060 #endif
10061         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10062                 raise_error_syntax("Unterminated quoted string");
10063         if (varnest != 0) {
10064                 startlinno = plinno;
10065                 /* { */
10066                 raise_error_syntax("Missing '}'");
10067         }
10068         USTPUTC('\0', out);
10069         len = out - (char *)stackblock();
10070         out = stackblock();
10071         if (eofmark == NULL) {
10072                 if ((c == '>' || c == '<')
10073                  && quotef == 0
10074                  && len <= 2
10075                  && (*out == '\0' || isdigit(*out))) {
10076                         PARSEREDIR();
10077                         return lasttoken = TREDIR;
10078                 } else {
10079                         pungetc();
10080                 }
10081         }
10082         quoteflag = quotef;
10083         backquotelist = bqlist;
10084         grabstackblock(len);
10085         wordtext = out;
10086         lasttoken = TWORD;
10087         return lasttoken;
10088 /* end of readtoken routine */
10089
10090 /*
10091  * Check to see whether we are at the end of the here document.  When this
10092  * is called, c is set to the first character of the next input line.  If
10093  * we are at the end of the here document, this routine sets the c to PEOF.
10094  */
10095 checkend: {
10096         if (eofmark) {
10097 #if ENABLE_ASH_ALIAS
10098                 if (c == PEOA) {
10099                         c = pgetc2();
10100                 }
10101 #endif
10102                 if (striptabs) {
10103                         while (c == '\t') {
10104                                 c = pgetc2();
10105                         }
10106                 }
10107                 if (c == *eofmark) {
10108                         if (pfgets(line, sizeof(line)) != NULL) {
10109                                 char *p, *q;
10110
10111                                 p = line;
10112                                 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10113                                 if (*p == '\n' && *q == '\0') {
10114                                         c = PEOF;
10115                                         plinno++;
10116                                         needprompt = doprompt;
10117                                 } else {
10118                                         pushstring(line, NULL);
10119                                 }
10120                         }
10121                 }
10122         }
10123         goto checkend_return;
10124 }
10125
10126 /*
10127  * Parse a redirection operator.  The variable "out" points to a string
10128  * specifying the fd to be redirected.  The variable "c" contains the
10129  * first character of the redirection operator.
10130  */
10131 parseredir: {
10132         char fd = *out;
10133         union node *np;
10134
10135         np = stalloc(sizeof(struct nfile));
10136         if (c == '>') {
10137                 np->nfile.fd = 1;
10138                 c = pgetc();
10139                 if (c == '>')
10140                         np->type = NAPPEND;
10141                 else if (c == '|')
10142                         np->type = NCLOBBER;
10143                 else if (c == '&')
10144                         np->type = NTOFD;
10145                 else {
10146                         np->type = NTO;
10147                         pungetc();
10148                 }
10149         } else {        /* c == '<' */
10150                 np->nfile.fd = 0;
10151                 c = pgetc();
10152                 switch (c) {
10153                 case '<':
10154                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10155                                 np = stalloc(sizeof(struct nhere));
10156                                 np->nfile.fd = 0;
10157                         }
10158                         np->type = NHERE;
10159                         heredoc = stalloc(sizeof(struct heredoc));
10160                         heredoc->here = np;
10161                         c = pgetc();
10162                         if (c == '-') {
10163                                 heredoc->striptabs = 1;
10164                         } else {
10165                                 heredoc->striptabs = 0;
10166                                 pungetc();
10167                         }
10168                         break;
10169
10170                 case '&':
10171                         np->type = NFROMFD;
10172                         break;
10173
10174                 case '>':
10175                         np->type = NFROMTO;
10176                         break;
10177
10178                 default:
10179                         np->type = NFROM;
10180                         pungetc();
10181                         break;
10182                 }
10183         }
10184         if (fd != '\0')
10185                 np->nfile.fd = fd - '0';
10186         redirnode = np;
10187         goto parseredir_return;
10188 }
10189
10190 /*
10191  * Parse a substitution.  At this point, we have read the dollar sign
10192  * and nothing else.
10193  */
10194
10195 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10196  * (assuming ascii char codes, as the original implementation did) */
10197 #define is_special(c) \
10198         ((((unsigned int)c) - 33 < 32) \
10199                         && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10200 parsesub: {
10201         int subtype;
10202         int typeloc;
10203         int flags;
10204         char *p;
10205         static const char types[] = "}-+?=";
10206
10207         c = pgetc();
10208         if (
10209                 c <= PEOA_OR_PEOF  ||
10210                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10211         ) {
10212                 USTPUTC('$', out);
10213                 pungetc();
10214         } else if (c == '(') {  /* $(command) or $((arith)) */
10215                 if (pgetc() == '(') {
10216 #if ENABLE_ASH_MATH_SUPPORT
10217                         PARSEARITH();
10218 #else
10219                         raise_error_syntax("We unsupport $((arith))");
10220 #endif
10221                 } else {
10222                         pungetc();
10223                         PARSEBACKQNEW();
10224                 }
10225         } else {
10226                 USTPUTC(CTLVAR, out);
10227                 typeloc = out - (char *)stackblock();
10228                 USTPUTC(VSNORMAL, out);
10229                 subtype = VSNORMAL;
10230                 if (c == '{') {
10231                         c = pgetc();
10232                         if (c == '#') {
10233                                 c = pgetc();
10234                                 if (c == '}')
10235                                         c = '#';
10236                                 else
10237                                         subtype = VSLENGTH;
10238                         } else
10239                                 subtype = 0;
10240                 }
10241                 if (c > PEOA_OR_PEOF && is_name(c)) {
10242                         do {
10243                                 STPUTC(c, out);
10244                                 c = pgetc();
10245                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10246                 } else if (isdigit(c)) {
10247                         do {
10248                                 STPUTC(c, out);
10249                                 c = pgetc();
10250                         } while (isdigit(c));
10251                 } else if (is_special(c)) {
10252                         USTPUTC(c, out);
10253                         c = pgetc();
10254                 } else
10255  badsub:                raise_error_syntax("Bad substitution");
10256
10257                 STPUTC('=', out);
10258                 flags = 0;
10259                 if (subtype == 0) {
10260                         switch (c) {
10261                         case ':':
10262                                 flags = VSNUL;
10263                                 c = pgetc();
10264                                 /*FALLTHROUGH*/
10265                         default:
10266                                 p = strchr(types, c);
10267                                 if (p == NULL)
10268                                         goto badsub;
10269                                 subtype = p - types + VSNORMAL;
10270                                 break;
10271                         case '%':
10272                         case '#':
10273                                 {
10274                                         int cc = c;
10275                                         subtype = c == '#' ? VSTRIMLEFT :
10276                                                              VSTRIMRIGHT;
10277                                         c = pgetc();
10278                                         if (c == cc)
10279                                                 subtype++;
10280                                         else
10281                                                 pungetc();
10282                                         break;
10283                                 }
10284                         }
10285                 } else {
10286                         pungetc();
10287                 }
10288                 if (dblquote || arinest)
10289                         flags |= VSQUOTE;
10290                 *((char *)stackblock() + typeloc) = subtype | flags;
10291                 if (subtype != VSNORMAL) {
10292                         varnest++;
10293                         if (dblquote || arinest) {
10294                                 dqvarnest++;
10295                         }
10296                 }
10297         }
10298         goto parsesub_return;
10299 }
10300
10301 /*
10302  * Called to parse command substitutions.  Newstyle is set if the command
10303  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10304  * list of commands (passed by reference), and savelen is the number of
10305  * characters on the top of the stack which must be preserved.
10306  */
10307 parsebackq: {
10308         struct nodelist **nlpp;
10309         int savepbq;
10310         union node *n;
10311         char *volatile str;
10312         struct jmploc jmploc;
10313         struct jmploc *volatile savehandler;
10314         size_t savelen;
10315         int saveprompt = 0;
10316 #ifdef __GNUC__
10317         (void) &saveprompt;
10318 #endif
10319
10320         savepbq = parsebackquote;
10321         if (setjmp(jmploc.loc)) {
10322                 if (str)
10323                         free(str);
10324                 parsebackquote = 0;
10325                 exception_handler = savehandler;
10326                 longjmp(exception_handler->loc, 1);
10327         }
10328         INT_OFF;
10329         str = NULL;
10330         savelen = out - (char *)stackblock();
10331         if (savelen > 0) {
10332                 str = ckmalloc(savelen);
10333                 memcpy(str, stackblock(), savelen);
10334         }
10335         savehandler = exception_handler;
10336         exception_handler = &jmploc;
10337         INT_ON;
10338         if (oldstyle) {
10339                 /* We must read until the closing backquote, giving special
10340                    treatment to some slashes, and then push the string and
10341                    reread it as input, interpreting it normally.  */
10342                 char *pout;
10343                 int pc;
10344                 size_t psavelen;
10345                 char *pstr;
10346
10347
10348                 STARTSTACKSTR(pout);
10349                 for (;;) {
10350                         if (needprompt) {
10351                                 setprompt(2);
10352                         }
10353                         pc = pgetc();
10354                         switch (pc) {
10355                         case '`':
10356                                 goto done;
10357
10358                         case '\\':
10359                                 pc = pgetc();
10360                                 if (pc == '\n') {
10361                                         plinno++;
10362                                         if (doprompt)
10363                                                 setprompt(2);
10364                                         /*
10365                                          * If eating a newline, avoid putting
10366                                          * the newline into the new character
10367                                          * stream (via the STPUTC after the
10368                                          * switch).
10369                                          */
10370                                         continue;
10371                                 }
10372                                 if (pc != '\\' && pc != '`' && pc != '$'
10373                                  && (!dblquote || pc != '"'))
10374                                         STPUTC('\\', pout);
10375                                 if (pc > PEOA_OR_PEOF) {
10376                                         break;
10377                                 }
10378                                 /* fall through */
10379
10380                         case PEOF:
10381 #if ENABLE_ASH_ALIAS
10382                         case PEOA:
10383 #endif
10384                                 startlinno = plinno;
10385                                 raise_error_syntax("EOF in backquote substitution");
10386
10387                         case '\n':
10388                                 plinno++;
10389                                 needprompt = doprompt;
10390                                 break;
10391
10392                         default:
10393                                 break;
10394                         }
10395                         STPUTC(pc, pout);
10396                 }
10397  done:
10398                 STPUTC('\0', pout);
10399                 psavelen = pout - (char *)stackblock();
10400                 if (psavelen > 0) {
10401                         pstr = grabstackstr(pout);
10402                         setinputstring(pstr);
10403                 }
10404         }
10405         nlpp = &bqlist;
10406         while (*nlpp)
10407                 nlpp = &(*nlpp)->next;
10408         *nlpp = stalloc(sizeof(**nlpp));
10409         (*nlpp)->next = NULL;
10410         parsebackquote = oldstyle;
10411
10412         if (oldstyle) {
10413                 saveprompt = doprompt;
10414                 doprompt = 0;
10415         }
10416
10417         n = list(2);
10418
10419         if (oldstyle)
10420                 doprompt = saveprompt;
10421         else if (readtoken() != TRP)
10422                 raise_error_unexpected_syntax(TRP);
10423
10424         (*nlpp)->n = n;
10425         if (oldstyle) {
10426                 /*
10427                  * Start reading from old file again, ignoring any pushed back
10428                  * tokens left from the backquote parsing
10429                  */
10430                 popfile();
10431                 tokpushback = 0;
10432         }
10433         while (stackblocksize() <= savelen)
10434                 growstackblock();
10435         STARTSTACKSTR(out);
10436         if (str) {
10437                 memcpy(out, str, savelen);
10438                 STADJUST(savelen, out);
10439                 INT_OFF;
10440                 free(str);
10441                 str = NULL;
10442                 INT_ON;
10443         }
10444         parsebackquote = savepbq;
10445         exception_handler = savehandler;
10446         if (arinest || dblquote)
10447                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10448         else
10449                 USTPUTC(CTLBACKQ, out);
10450         if (oldstyle)
10451                 goto parsebackq_oldreturn;
10452         goto parsebackq_newreturn;
10453 }
10454
10455 #if ENABLE_ASH_MATH_SUPPORT
10456 /*
10457  * Parse an arithmetic expansion (indicate start of one and set state)
10458  */
10459 parsearith: {
10460         if (++arinest == 1) {
10461                 prevsyntax = syntax;
10462                 syntax = ARISYNTAX;
10463                 USTPUTC(CTLARI, out);
10464                 if (dblquote)
10465                         USTPUTC('"', out);
10466                 else
10467                         USTPUTC(' ', out);
10468         } else {
10469                 /*
10470                  * we collapse embedded arithmetic expansion to
10471                  * parenthesis, which should be equivalent
10472                  */
10473                 USTPUTC('(', out);
10474         }
10475         goto parsearith_return;
10476 }
10477 #endif
10478
10479 } /* end of readtoken */
10480
10481 /*
10482  * Read the next input token.
10483  * If the token is a word, we set backquotelist to the list of cmds in
10484  *      backquotes.  We set quoteflag to true if any part of the word was
10485  *      quoted.
10486  * If the token is TREDIR, then we set redirnode to a structure containing
10487  *      the redirection.
10488  * In all cases, the variable startlinno is set to the number of the line
10489  *      on which the token starts.
10490  *
10491  * [Change comment:  here documents and internal procedures]
10492  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10493  *  word parsing code into a separate routine.  In this case, readtoken
10494  *  doesn't need to have any internal procedures, but parseword does.
10495  *  We could also make parseoperator in essence the main routine, and
10496  *  have parseword (readtoken1?) handle both words and redirection.]
10497  */
10498 #define NEW_xxreadtoken
10499 #ifdef NEW_xxreadtoken
10500 /* singles must be first! */
10501 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10502
10503 static const char xxreadtoken_tokens[] = {
10504         TNL, TLP, TRP,          /* only single occurrence allowed */
10505         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10506         TEOF,                   /* corresponds to trailing nul */
10507         TAND, TOR, TENDCASE,    /* if double occurrence */
10508 };
10509
10510 #define xxreadtoken_doubles \
10511         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10512 #define xxreadtoken_singles \
10513         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10514
10515 static int
10516 xxreadtoken(void)
10517 {
10518         int c;
10519
10520         if (tokpushback) {
10521                 tokpushback = 0;
10522                 return lasttoken;
10523         }
10524         if (needprompt) {
10525                 setprompt(2);
10526         }
10527         startlinno = plinno;
10528         for (;;) {                      /* until token or start of word found */
10529                 c = pgetc_macro();
10530
10531                 if ((c != ' ') && (c != '\t')
10532 #if ENABLE_ASH_ALIAS
10533                  && (c != PEOA)
10534 #endif
10535                 ) {
10536                         if (c == '#') {
10537                                 while ((c = pgetc()) != '\n' && c != PEOF);
10538                                 pungetc();
10539                         } else if (c == '\\') {
10540                                 if (pgetc() != '\n') {
10541                                         pungetc();
10542                                         goto READTOKEN1;
10543                                 }
10544                                 startlinno = ++plinno;
10545                                 if (doprompt)
10546                                         setprompt(2);
10547                         } else {
10548                                 const char *p
10549                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10550
10551                                 if (c != PEOF) {
10552                                         if (c == '\n') {
10553                                                 plinno++;
10554                                                 needprompt = doprompt;
10555                                         }
10556
10557                                         p = strchr(xxreadtoken_chars, c);
10558                                         if (p == NULL) {
10559  READTOKEN1:
10560                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10561                                         }
10562
10563                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10564                                                 if (pgetc() == *p) {    /* double occurrence? */
10565                                                         p += xxreadtoken_doubles + 1;
10566                                                 } else {
10567                                                         pungetc();
10568                                                 }
10569                                         }
10570                                 }
10571                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10572                         }
10573                 }
10574         } /* for */
10575 }
10576 #else
10577 #define RETURN(token)   return lasttoken = token
10578 static int
10579 xxreadtoken(void)
10580 {
10581         int c;
10582
10583         if (tokpushback) {
10584                 tokpushback = 0;
10585                 return lasttoken;
10586         }
10587         if (needprompt) {
10588                 setprompt(2);
10589         }
10590         startlinno = plinno;
10591         for (;;) {      /* until token or start of word found */
10592                 c = pgetc_macro();
10593                 switch (c) {
10594                 case ' ': case '\t':
10595 #if ENABLE_ASH_ALIAS
10596                 case PEOA:
10597 #endif
10598                         continue;
10599                 case '#':
10600                         while ((c = pgetc()) != '\n' && c != PEOF);
10601                         pungetc();
10602                         continue;
10603                 case '\\':
10604                         if (pgetc() == '\n') {
10605                                 startlinno = ++plinno;
10606                                 if (doprompt)
10607                                         setprompt(2);
10608                                 continue;
10609                         }
10610                         pungetc();
10611                         goto breakloop;
10612                 case '\n':
10613                         plinno++;
10614                         needprompt = doprompt;
10615                         RETURN(TNL);
10616                 case PEOF:
10617                         RETURN(TEOF);
10618                 case '&':
10619                         if (pgetc() == '&')
10620                                 RETURN(TAND);
10621                         pungetc();
10622                         RETURN(TBACKGND);
10623                 case '|':
10624                         if (pgetc() == '|')
10625                                 RETURN(TOR);
10626                         pungetc();
10627                         RETURN(TPIPE);
10628                 case ';':
10629                         if (pgetc() == ';')
10630                                 RETURN(TENDCASE);
10631                         pungetc();
10632                         RETURN(TSEMI);
10633                 case '(':
10634                         RETURN(TLP);
10635                 case ')':
10636                         RETURN(TRP);
10637                 default:
10638                         goto breakloop;
10639                 }
10640         }
10641  breakloop:
10642         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10643 #undef RETURN
10644 }
10645 #endif /* NEW_xxreadtoken */
10646
10647 static int
10648 readtoken(void)
10649 {
10650         int t;
10651 #if DEBUG
10652         int alreadyseen = tokpushback;
10653 #endif
10654
10655 #if ENABLE_ASH_ALIAS
10656  top:
10657 #endif
10658
10659         t = xxreadtoken();
10660
10661         /*
10662          * eat newlines
10663          */
10664         if (checkkwd & CHKNL) {
10665                 while (t == TNL) {
10666                         parseheredoc();
10667                         t = xxreadtoken();
10668                 }
10669         }
10670
10671         if (t != TWORD || quoteflag) {
10672                 goto out;
10673         }
10674
10675         /*
10676          * check for keywords
10677          */
10678         if (checkkwd & CHKKWD) {
10679                 const char *const *pp;
10680
10681                 pp = findkwd(wordtext);
10682                 if (pp) {
10683                         lasttoken = t = pp - tokname_array;
10684                         TRACE(("keyword %s recognized\n", tokname(t)));
10685                         goto out;
10686                 }
10687         }
10688
10689         if (checkkwd & CHKALIAS) {
10690 #if ENABLE_ASH_ALIAS
10691                 struct alias *ap;
10692                 ap = lookupalias(wordtext, 1);
10693                 if (ap != NULL) {
10694                         if (*ap->val) {
10695                                 pushstring(ap->val, ap);
10696                         }
10697                         goto top;
10698                 }
10699 #endif
10700         }
10701  out:
10702         checkkwd = 0;
10703 #if DEBUG
10704         if (!alreadyseen)
10705                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10706         else
10707                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10708 #endif
10709         return t;
10710 }
10711
10712 static char
10713 peektoken(void)
10714 {
10715         int t;
10716
10717         t = readtoken();
10718         tokpushback++;
10719         return tokname_array[t][0];
10720 }
10721
10722 /*
10723  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
10724  * valid parse tree indicating a blank line.)
10725  */
10726 static union node *
10727 parsecmd(int interact)
10728 {
10729         int t;
10730
10731         tokpushback = 0;
10732         doprompt = interact;
10733         if (doprompt)
10734                 setprompt(doprompt);
10735         needprompt = 0;
10736         t = readtoken();
10737         if (t == TEOF)
10738                 return NEOF;
10739         if (t == TNL)
10740                 return NULL;
10741         tokpushback++;
10742         return list(1);
10743 }
10744
10745 /*
10746  * Input any here documents.
10747  */
10748 static void
10749 parseheredoc(void)
10750 {
10751         struct heredoc *here;
10752         union node *n;
10753
10754         here = heredoclist;
10755         heredoclist = 0;
10756
10757         while (here) {
10758                 if (needprompt) {
10759                         setprompt(2);
10760                 }
10761                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10762                                 here->eofmark, here->striptabs);
10763                 n = stalloc(sizeof(struct narg));
10764                 n->narg.type = NARG;
10765                 n->narg.next = NULL;
10766                 n->narg.text = wordtext;
10767                 n->narg.backquote = backquotelist;
10768                 here->here->nhere.doc = n;
10769                 here = here->next;
10770         }
10771 }
10772
10773
10774 /*
10775  * called by editline -- any expansions to the prompt should be added here.
10776  */
10777 #if ENABLE_ASH_EXPAND_PRMT
10778 static const char *
10779 expandstr(const char *ps)
10780 {
10781         union node n;
10782
10783         /* XXX Fix (char *) cast. */
10784         setinputstring((char *)ps);
10785         readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10786         popfile();
10787
10788         n.narg.type = NARG;
10789         n.narg.next = NULL;
10790         n.narg.text = wordtext;
10791         n.narg.backquote = backquotelist;
10792
10793         expandarg(&n, NULL, 0);
10794         return stackblock();
10795 }
10796 #endif
10797
10798 /*
10799  * Execute a command or commands contained in a string.
10800  */
10801 static int
10802 evalstring(char *s, int mask)
10803 {
10804         union node *n;
10805         struct stackmark smark;
10806         int skip;
10807
10808         setinputstring(s);
10809         setstackmark(&smark);
10810
10811         skip = 0;
10812         while ((n = parsecmd(0)) != NEOF) {
10813                 evaltree(n, 0);
10814                 popstackmark(&smark);
10815                 skip = evalskip;
10816                 if (skip)
10817                         break;
10818         }
10819         popfile();
10820
10821         skip &= mask;
10822         evalskip = skip;
10823         return skip;
10824 }
10825
10826 /*
10827  * The eval command.
10828  */
10829 static int
10830 evalcmd(int argc, char **argv)
10831 {
10832         char *p;
10833         char *concat;
10834         char **ap;
10835
10836         if (argc > 1) {
10837                 p = argv[1];
10838                 if (argc > 2) {
10839                         STARTSTACKSTR(concat);
10840                         ap = argv + 2;
10841                         for (;;) {
10842                                 concat = stack_putstr(p, concat);
10843                                 p = *ap++;
10844                                 if (p == NULL)
10845                                         break;
10846                                 STPUTC(' ', concat);
10847                         }
10848                         STPUTC('\0', concat);
10849                         p = grabstackstr(concat);
10850                 }
10851                 evalstring(p, ~SKIPEVAL);
10852
10853         }
10854         return exitstatus;
10855 }
10856
10857 /*
10858  * Read and execute commands.  "Top" is nonzero for the top level command
10859  * loop; it turns on prompting if the shell is interactive.
10860  */
10861 static int
10862 cmdloop(int top)
10863 {
10864         union node *n;
10865         struct stackmark smark;
10866         int inter;
10867         int numeof = 0;
10868
10869         TRACE(("cmdloop(%d) called\n", top));
10870         for (;;) {
10871                 int skip;
10872
10873                 setstackmark(&smark);
10874 #if JOBS
10875                 if (jobctl)
10876                         showjobs(stderr, SHOW_CHANGED);
10877 #endif
10878                 inter = 0;
10879                 if (iflag && top) {
10880                         inter++;
10881 #if ENABLE_ASH_MAIL
10882                         chkmail();
10883 #endif
10884                 }
10885                 n = parsecmd(inter);
10886                 /* showtree(n); DEBUG */
10887                 if (n == NEOF) {
10888                         if (!top || numeof >= 50)
10889                                 break;
10890                         if (!stoppedjobs()) {
10891                                 if (!Iflag)
10892                                         break;
10893                                 out2str("\nUse \"exit\" to leave shell.\n");
10894                         }
10895                         numeof++;
10896                 } else if (nflag == 0) {
10897                         job_warning = (job_warning == 2) ? 1 : 0;
10898                         numeof = 0;
10899                         evaltree(n, 0);
10900                 }
10901                 popstackmark(&smark);
10902                 skip = evalskip;
10903
10904                 if (skip) {
10905                         evalskip = 0;
10906                         return skip & SKIPEVAL;
10907                 }
10908         }
10909         return 0;
10910 }
10911
10912 /*
10913  * Take commands from a file.  To be compatible we should do a path
10914  * search for the file, which is necessary to find sub-commands.
10915  */
10916 static char *
10917 find_dot_file(char *name)
10918 {
10919         char *fullname;
10920         const char *path = pathval();
10921         struct stat statb;
10922
10923         /* don't try this for absolute or relative paths */
10924         if (strchr(name, '/'))
10925                 return name;
10926
10927         while ((fullname = padvance(&path, name)) != NULL) {
10928                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
10929                         /*
10930                          * Don't bother freeing here, since it will
10931                          * be freed by the caller.
10932                          */
10933                         return fullname;
10934                 }
10935                 stunalloc(fullname);
10936         }
10937
10938         /* not found in the PATH */
10939         ash_msg_and_raise_error("%s: not found", name);
10940         /* NOTREACHED */
10941 }
10942
10943 static int
10944 dotcmd(int argc, char **argv)
10945 {
10946         struct strlist *sp;
10947         volatile struct shparam saveparam;
10948         int status = 0;
10949
10950         for (sp = cmdenviron; sp; sp = sp->next)
10951                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10952
10953         if (argc >= 2) {        /* That's what SVR2 does */
10954                 char *fullname;
10955
10956                 fullname = find_dot_file(argv[1]);
10957
10958                 if (argc > 2) {
10959                         saveparam = shellparam;
10960                         shellparam.malloc = 0;
10961                         shellparam.nparam = argc - 2;
10962                         shellparam.p = argv + 2;
10963                 };
10964
10965                 setinputfile(fullname, INPUT_PUSH_FILE);
10966                 commandname = fullname;
10967                 cmdloop(0);
10968                 popfile();
10969
10970                 if (argc > 2) {
10971                         freeparam(&shellparam);
10972                         shellparam = saveparam;
10973                 };
10974                 status = exitstatus;
10975         }
10976         return status;
10977 }
10978
10979 static int
10980 exitcmd(int argc, char **argv)
10981 {
10982         if (stoppedjobs())
10983                 return 0;
10984         if (argc > 1)
10985                 exitstatus = number(argv[1]);
10986         raise_exception(EXEXIT);
10987         /* NOTREACHED */
10988 }
10989
10990 #if ENABLE_ASH_BUILTIN_ECHO
10991 static int
10992 echocmd(int argc, char **argv)
10993 {
10994         return bb_echo(argv);
10995 }
10996 #endif
10997
10998 #if ENABLE_ASH_BUILTIN_TEST
10999 static int
11000 testcmd(int argc, char **argv)
11001 {
11002         return bb_test(argc, argv);
11003 }
11004 #endif
11005
11006 /*
11007  * Read a file containing shell functions.
11008  */
11009 static void
11010 readcmdfile(char *name)
11011 {
11012         setinputfile(name, INPUT_PUSH_FILE);
11013         cmdloop(0);
11014         popfile();
11015 }
11016
11017
11018 /* ============ find_command inplementation */
11019
11020 /*
11021  * Resolve a command name.  If you change this routine, you may have to
11022  * change the shellexec routine as well.
11023  */
11024 static void
11025 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11026 {
11027         struct tblentry *cmdp;
11028         int idx;
11029         int prev;
11030         char *fullname;
11031         struct stat statb;
11032         int e;
11033         int updatetbl;
11034         struct builtincmd *bcmd;
11035
11036         /* If name contains a slash, don't use PATH or hash table */
11037         if (strchr(name, '/') != NULL) {
11038                 entry->u.index = -1;
11039                 if (act & DO_ABS) {
11040                         while (stat(name, &statb) < 0) {
11041 #ifdef SYSV
11042                                 if (errno == EINTR)
11043                                         continue;
11044 #endif
11045                                 entry->cmdtype = CMDUNKNOWN;
11046                                 return;
11047                         }
11048                 }
11049                 entry->cmdtype = CMDNORMAL;
11050                 return;
11051         }
11052
11053 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11054
11055         updatetbl = (path == pathval());
11056         if (!updatetbl) {
11057                 act |= DO_ALTPATH;
11058                 if (strstr(path, "%builtin") != NULL)
11059                         act |= DO_ALTBLTIN;
11060         }
11061
11062         /* If name is in the table, check answer will be ok */
11063         cmdp = cmdlookup(name, 0);
11064         if (cmdp != NULL) {
11065                 int bit;
11066
11067                 switch (cmdp->cmdtype) {
11068                 default:
11069 #if DEBUG
11070                         abort();
11071 #endif
11072                 case CMDNORMAL:
11073                         bit = DO_ALTPATH;
11074                         break;
11075                 case CMDFUNCTION:
11076                         bit = DO_NOFUNC;
11077                         break;
11078                 case CMDBUILTIN:
11079                         bit = DO_ALTBLTIN;
11080                         break;
11081                 }
11082                 if (act & bit) {
11083                         updatetbl = 0;
11084                         cmdp = NULL;
11085                 } else if (cmdp->rehash == 0)
11086                         /* if not invalidated by cd, we're done */
11087                         goto success;
11088         }
11089
11090         /* If %builtin not in path, check for builtin next */
11091         bcmd = find_builtin(name);
11092         if (bcmd) {
11093                 if (IS_BUILTIN_REGULAR(bcmd))
11094                         goto builtin_success;
11095                 if (act & DO_ALTPATH) {
11096                         if (!(act & DO_ALTBLTIN))
11097                                 goto builtin_success;
11098                 } else if (builtinloc <= 0) {
11099                         goto builtin_success;
11100                 }
11101         }
11102
11103 #if ENABLE_FEATURE_SH_STANDALONE
11104         if (find_applet_by_name(name)) {
11105                 entry->cmdtype = CMDNORMAL;
11106                 entry->u.index = -1;
11107                 return;
11108         }
11109 #endif
11110
11111         /* We have to search path. */
11112         prev = -1;              /* where to start */
11113         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11114                 if (cmdp->cmdtype == CMDBUILTIN)
11115                         prev = builtinloc;
11116                 else
11117                         prev = cmdp->param.index;
11118         }
11119
11120         e = ENOENT;
11121         idx = -1;
11122  loop:
11123         while ((fullname = padvance(&path, name)) != NULL) {
11124                 stunalloc(fullname);
11125                 idx++;
11126                 if (pathopt) {
11127                         if (prefix(pathopt, "builtin")) {
11128                                 if (bcmd)
11129                                         goto builtin_success;
11130                                 continue;
11131                         } else if (!(act & DO_NOFUNC) &&
11132                                    prefix(pathopt, "func")) {
11133                                 /* handled below */
11134                         } else {
11135                                 /* ignore unimplemented options */
11136                                 continue;
11137                         }
11138                 }
11139                 /* if rehash, don't redo absolute path names */
11140                 if (fullname[0] == '/' && idx <= prev) {
11141                         if (idx < prev)
11142                                 continue;
11143                         TRACE(("searchexec \"%s\": no change\n", name));
11144                         goto success;
11145                 }
11146                 while (stat(fullname, &statb) < 0) {
11147 #ifdef SYSV
11148                         if (errno == EINTR)
11149                                 continue;
11150 #endif
11151                         if (errno != ENOENT && errno != ENOTDIR)
11152                                 e = errno;
11153                         goto loop;
11154                 }
11155                 e = EACCES;     /* if we fail, this will be the error */
11156                 if (!S_ISREG(statb.st_mode))
11157                         continue;
11158                 if (pathopt) {          /* this is a %func directory */
11159                         stalloc(strlen(fullname) + 1);
11160                         readcmdfile(fullname);
11161                         cmdp = cmdlookup(name, 0);
11162                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11163                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11164                         stunalloc(fullname);
11165                         goto success;
11166                 }
11167                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11168                 if (!updatetbl) {
11169                         entry->cmdtype = CMDNORMAL;
11170                         entry->u.index = idx;
11171                         return;
11172                 }
11173                 INT_OFF;
11174                 cmdp = cmdlookup(name, 1);
11175                 cmdp->cmdtype = CMDNORMAL;
11176                 cmdp->param.index = idx;
11177                 INT_ON;
11178                 goto success;
11179         }
11180
11181         /* We failed.  If there was an entry for this command, delete it */
11182         if (cmdp && updatetbl)
11183                 delete_cmd_entry();
11184         if (act & DO_ERR)
11185                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11186         entry->cmdtype = CMDUNKNOWN;
11187         return;
11188
11189  builtin_success:
11190         if (!updatetbl) {
11191                 entry->cmdtype = CMDBUILTIN;
11192                 entry->u.cmd = bcmd;
11193                 return;
11194         }
11195         INT_OFF;
11196         cmdp = cmdlookup(name, 1);
11197         cmdp->cmdtype = CMDBUILTIN;
11198         cmdp->param.cmd = bcmd;
11199         INT_ON;
11200  success:
11201         cmdp->rehash = 0;
11202         entry->cmdtype = cmdp->cmdtype;
11203         entry->u = cmdp->param;
11204 }
11205
11206
11207 /* ============ trap.c */
11208
11209 /*
11210  * The trap builtin.
11211  */
11212 static int
11213 trapcmd(int argc, char **argv)
11214 {
11215         char *action;
11216         char **ap;
11217         int signo;
11218
11219         nextopt(nullstr);
11220         ap = argptr;
11221         if (!*ap) {
11222                 for (signo = 0; signo < NSIG; signo++) {
11223                         if (trap[signo] != NULL) {
11224                                 const char *sn;
11225
11226                                 sn = get_signame(signo);
11227                                 out1fmt("trap -- %s %s\n",
11228                                         single_quote(trap[signo]), sn);
11229                         }
11230                 }
11231                 return 0;
11232         }
11233         if (!ap[1])
11234                 action = NULL;
11235         else
11236                 action = *ap++;
11237         while (*ap) {
11238                 signo = get_signum(*ap);
11239                 if (signo < 0)
11240                         ash_msg_and_raise_error("%s: bad trap", *ap);
11241                 INT_OFF;
11242                 if (action) {
11243                         if (LONE_DASH(action))
11244                                 action = NULL;
11245                         else
11246                                 action = ckstrdup(action);
11247                 }
11248                 if (trap[signo])
11249                         free(trap[signo]);
11250                 trap[signo] = action;
11251                 if (signo != 0)
11252                         setsignal(signo);
11253                 INT_ON;
11254                 ap++;
11255         }
11256         return 0;
11257 }
11258
11259
11260 /* ============ Builtins */
11261
11262 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11263 /*
11264  * Lists available builtins
11265  */
11266 static int
11267 helpcmd(int argc, char **argv)
11268 {
11269         int col, i;
11270
11271         out1fmt("\nBuilt-in commands:\n-------------------\n");
11272         for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11273                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11274                                         builtintab[i].name + 1);
11275                 if (col > 60) {
11276                         out1fmt("\n");
11277                         col = 0;
11278                 }
11279         }
11280 #if ENABLE_FEATURE_SH_STANDALONE
11281         for (i = 0; i < NUM_APPLETS; i++) {
11282                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11283                 if (col > 60) {
11284                         out1fmt("\n");
11285                         col = 0;
11286                 }
11287         }
11288 #endif
11289         out1fmt("\n\n");
11290         return EXIT_SUCCESS;
11291 }
11292 #endif /* FEATURE_SH_EXTRA_QUIET */
11293
11294 /*
11295  * The export and readonly commands.
11296  */
11297 static int
11298 exportcmd(int argc, char **argv)
11299 {
11300         struct var *vp;
11301         char *name;
11302         const char *p;
11303         char **aptr;
11304         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11305
11306         if (nextopt("p") != 'p') {
11307                 aptr = argptr;
11308                 name = *aptr;
11309                 if (name) {
11310                         do {
11311                                 p = strchr(name, '=');
11312                                 if (p != NULL) {
11313                                         p++;
11314                                 } else {
11315                                         vp = *findvar(hashvar(name), name);
11316                                         if (vp) {
11317                                                 vp->flags |= flag;
11318                                                 continue;
11319                                         }
11320                                 }
11321                                 setvar(name, p, flag);
11322                         } while ((name = *++aptr) != NULL);
11323                         return 0;
11324                 }
11325         }
11326         showvars(argv[0], flag, 0);
11327         return 0;
11328 }
11329
11330 /*
11331  * Delete a function if it exists.
11332  */
11333 static void
11334 unsetfunc(const char *name)
11335 {
11336         struct tblentry *cmdp;
11337
11338         cmdp = cmdlookup(name, 0);
11339         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11340                 delete_cmd_entry();
11341 }
11342
11343 /*
11344  * The unset builtin command.  We unset the function before we unset the
11345  * variable to allow a function to be unset when there is a readonly variable
11346  * with the same name.
11347  */
11348 static int
11349 unsetcmd(int argc, char **argv)
11350 {
11351         char **ap;
11352         int i;
11353         int flag = 0;
11354         int ret = 0;
11355
11356         while ((i = nextopt("vf")) != '\0') {
11357                 flag = i;
11358         }
11359
11360         for (ap = argptr; *ap; ap++) {
11361                 if (flag != 'f') {
11362                         i = unsetvar(*ap);
11363                         ret |= i;
11364                         if (!(i & 2))
11365                                 continue;
11366                 }
11367                 if (flag != 'v')
11368                         unsetfunc(*ap);
11369         }
11370         return ret & 1;
11371 }
11372
11373
11374 /*      setmode.c      */
11375
11376 #include <sys/times.h>
11377
11378 static const unsigned char timescmd_str[] = {
11379         ' ',  offsetof(struct tms, tms_utime),
11380         '\n', offsetof(struct tms, tms_stime),
11381         ' ',  offsetof(struct tms, tms_cutime),
11382         '\n', offsetof(struct tms, tms_cstime),
11383         0
11384 };
11385
11386 static int
11387 timescmd(int ac, char **av)
11388 {
11389         long clk_tck, s, t;
11390         const unsigned char *p;
11391         struct tms buf;
11392
11393         clk_tck = sysconf(_SC_CLK_TCK);
11394         times(&buf);
11395
11396         p = timescmd_str;
11397         do {
11398                 t = *(clock_t *)(((char *) &buf) + p[1]);
11399                 s = t / clk_tck;
11400                 out1fmt("%ldm%ld.%.3lds%c",
11401                         s/60, s%60,
11402                         ((t - s * clk_tck) * 1000) / clk_tck,
11403                         p[0]);
11404         } while (*(p += 2));
11405
11406         return 0;
11407 }
11408
11409 #if ENABLE_ASH_MATH_SUPPORT
11410 static arith_t
11411 dash_arith(const char *s)
11412 {
11413         arith_t result;
11414         int errcode = 0;
11415
11416         INT_OFF;
11417         result = arith(s, &errcode);
11418         if (errcode < 0) {
11419                 if (errcode == -3)
11420                         ash_msg_and_raise_error("exponent less than 0");
11421                 if (errcode == -2)
11422                         ash_msg_and_raise_error("divide by zero");
11423                 if (errcode == -5)
11424                         ash_msg_and_raise_error("expression recursion loop detected");
11425                 raise_error_syntax(s);
11426         }
11427         INT_ON;
11428
11429         return result;
11430 }
11431
11432 /*
11433  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11434  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11435  *
11436  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11437  */
11438 static int
11439 letcmd(int argc, char **argv)
11440 {
11441         char **ap;
11442         arith_t i = 0;
11443
11444         ap = argv + 1;
11445         if (!*ap)
11446                 ash_msg_and_raise_error("expression expected");
11447         for (ap = argv + 1; *ap; ap++) {
11448                 i = dash_arith(*ap);
11449         }
11450
11451         return !i;
11452 }
11453 #endif /* ASH_MATH_SUPPORT */
11454
11455
11456 /* ============ miscbltin.c
11457  *
11458  * Miscellaneous builtins.
11459  */
11460
11461 #undef rflag
11462
11463 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11464 typedef enum __rlimit_resource rlim_t;
11465 #endif
11466
11467 /*
11468  * The read builtin.  The -e option causes backslashes to escape the
11469  * following character.
11470  *
11471  * This uses unbuffered input, which may be avoidable in some cases.
11472  */
11473 static int
11474 readcmd(int argc, char **argv)
11475 {
11476         char **ap;
11477         int backslash;
11478         char c;
11479         int rflag;
11480         char *prompt;
11481         const char *ifs;
11482         char *p;
11483         int startword;
11484         int status;
11485         int i;
11486 #if ENABLE_ASH_READ_NCHARS
11487         int nch_flag = 0;
11488         int nchars = 0;
11489         int silent = 0;
11490         struct termios tty, old_tty;
11491 #endif
11492 #if ENABLE_ASH_READ_TIMEOUT
11493         fd_set set;
11494         struct timeval ts;
11495
11496         ts.tv_sec = ts.tv_usec = 0;
11497 #endif
11498
11499         rflag = 0;
11500         prompt = NULL;
11501 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11502         while ((i = nextopt("p:rt:n:s")) != '\0')
11503 #elif ENABLE_ASH_READ_NCHARS
11504         while ((i = nextopt("p:rn:s")) != '\0')
11505 #elif ENABLE_ASH_READ_TIMEOUT
11506         while ((i = nextopt("p:rt:")) != '\0')
11507 #else
11508         while ((i = nextopt("p:r")) != '\0')
11509 #endif
11510         {
11511                 switch (i) {
11512                 case 'p':
11513                         prompt = optionarg;
11514                         break;
11515 #if ENABLE_ASH_READ_NCHARS
11516                 case 'n':
11517                         nchars = strtol(optionarg, &p, 10);
11518                         if (*p)
11519                                 ash_msg_and_raise_error("invalid count");
11520                         nch_flag = (nchars > 0);
11521                         break;
11522                 case 's':
11523                         silent = 1;
11524                         break;
11525 #endif
11526 #if ENABLE_ASH_READ_TIMEOUT
11527                 case 't':
11528                         ts.tv_sec = strtol(optionarg, &p, 10);
11529                         ts.tv_usec = 0;
11530                         if (*p == '.') {
11531                                 char *p2;
11532                                 if (*++p) {
11533                                         int scale;
11534                                         ts.tv_usec = strtol(p, &p2, 10);
11535                                         if (*p2)
11536                                                 ash_msg_and_raise_error("invalid timeout");
11537                                         scale = p2 - p;
11538                                         /* normalize to usec */
11539                                         if (scale > 6)
11540                                                 ash_msg_and_raise_error("invalid timeout");
11541                                         while (scale++ < 6)
11542                                                 ts.tv_usec *= 10;
11543                                 }
11544                         } else if (*p) {
11545                                 ash_msg_and_raise_error("invalid timeout");
11546                         }
11547                         if ( ! ts.tv_sec && ! ts.tv_usec)
11548                                 ash_msg_and_raise_error("invalid timeout");
11549                         break;
11550 #endif
11551                 case 'r':
11552                         rflag = 1;
11553                         break;
11554                 default:
11555                         break;
11556                 }
11557         }
11558         if (prompt && isatty(0)) {
11559                 out2str(prompt);
11560         }
11561         ap = argptr;
11562         if (*ap == NULL)
11563                 ash_msg_and_raise_error("arg count");
11564         ifs = bltinlookup("IFS");
11565         if (ifs == NULL)
11566                 ifs = defifs;
11567 #if ENABLE_ASH_READ_NCHARS
11568         if (nch_flag || silent) {
11569                 tcgetattr(0, &tty);
11570                 old_tty = tty;
11571                 if (nch_flag) {
11572                         tty.c_lflag &= ~ICANON;
11573                         tty.c_cc[VMIN] = nchars;
11574                 }
11575                 if (silent) {
11576                         tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11577
11578                 }
11579                 tcsetattr(0, TCSANOW, &tty);
11580         }
11581 #endif
11582 #if ENABLE_ASH_READ_TIMEOUT
11583         if (ts.tv_sec || ts.tv_usec) {
11584                 FD_ZERO (&set);
11585                 FD_SET (0, &set);
11586
11587                 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11588                 if (!i) {
11589 #if ENABLE_ASH_READ_NCHARS
11590                         if (nch_flag)
11591                                 tcsetattr(0, TCSANOW, &old_tty);
11592 #endif
11593                         return 1;
11594                 }
11595         }
11596 #endif
11597         status = 0;
11598         startword = 1;
11599         backslash = 0;
11600         STARTSTACKSTR(p);
11601 #if ENABLE_ASH_READ_NCHARS
11602         while (!nch_flag || nchars--)
11603 #else
11604         for (;;)
11605 #endif
11606         {
11607                 if (read(0, &c, 1) != 1) {
11608                         status = 1;
11609                         break;
11610                 }
11611                 if (c == '\0')
11612                         continue;
11613                 if (backslash) {
11614                         backslash = 0;
11615                         if (c != '\n')
11616                                 goto put;
11617                         continue;
11618                 }
11619                 if (!rflag && c == '\\') {
11620                         backslash++;
11621                         continue;
11622                 }
11623                 if (c == '\n')
11624                         break;
11625                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11626                         continue;
11627                 }
11628                 startword = 0;
11629                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11630                         STACKSTRNUL(p);
11631                         setvar(*ap, stackblock(), 0);
11632                         ap++;
11633                         startword = 1;
11634                         STARTSTACKSTR(p);
11635                 } else {
11636  put:
11637                         STPUTC(c, p);
11638                 }
11639         }
11640 #if ENABLE_ASH_READ_NCHARS
11641         if (nch_flag || silent)
11642                 tcsetattr(0, TCSANOW, &old_tty);
11643 #endif
11644
11645         STACKSTRNUL(p);
11646         /* Remove trailing blanks */
11647         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11648                 *p = '\0';
11649         setvar(*ap, stackblock(), 0);
11650         while (*++ap != NULL)
11651                 setvar(*ap, nullstr, 0);
11652         return status;
11653 }
11654
11655 static int
11656 umaskcmd(int argc, char **argv)
11657 {
11658         static const char permuser[3] = "ugo";
11659         static const char permmode[3] = "rwx";
11660         static const short int permmask[] = {
11661                 S_IRUSR, S_IWUSR, S_IXUSR,
11662                 S_IRGRP, S_IWGRP, S_IXGRP,
11663                 S_IROTH, S_IWOTH, S_IXOTH
11664         };
11665
11666         char *ap;
11667         mode_t mask;
11668         int i;
11669         int symbolic_mode = 0;
11670
11671         while (nextopt("S") != '\0') {
11672                 symbolic_mode = 1;
11673         }
11674
11675         INT_OFF;
11676         mask = umask(0);
11677         umask(mask);
11678         INT_ON;
11679
11680         ap = *argptr;
11681         if (ap == NULL) {
11682                 if (symbolic_mode) {
11683                         char buf[18];
11684                         char *p = buf;
11685
11686                         for (i = 0; i < 3; i++) {
11687                                 int j;
11688
11689                                 *p++ = permuser[i];
11690                                 *p++ = '=';
11691                                 for (j = 0; j < 3; j++) {
11692                                         if ((mask & permmask[3 * i + j]) == 0) {
11693                                                 *p++ = permmode[j];
11694                                         }
11695                                 }
11696                                 *p++ = ',';
11697                         }
11698                         *--p = 0;
11699                         puts(buf);
11700                 } else {
11701                         out1fmt("%.4o\n", mask);
11702                 }
11703         } else {
11704                 if (isdigit((unsigned char) *ap)) {
11705                         mask = 0;
11706                         do {
11707                                 if (*ap >= '8' || *ap < '0')
11708                                         ash_msg_and_raise_error(illnum, argv[1]);
11709                                 mask = (mask << 3) + (*ap - '0');
11710                         } while (*++ap != '\0');
11711                         umask(mask);
11712                 } else {
11713                         mask = ~mask & 0777;
11714                         if (!bb_parse_mode(ap, &mask)) {
11715                                 ash_msg_and_raise_error("illegal mode: %s", ap);
11716                         }
11717                         umask(~mask & 0777);
11718                 }
11719         }
11720         return 0;
11721 }
11722
11723 /*
11724  * ulimit builtin
11725  *
11726  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11727  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11728  * ash by J.T. Conklin.
11729  *
11730  * Public domain.
11731  */
11732
11733 struct limits {
11734         const char *name;
11735         int     cmd;
11736         int     factor; /* multiply by to get rlim_{cur,max} values */
11737         char    option;
11738 };
11739
11740 static const struct limits limits[] = {
11741 #ifdef RLIMIT_CPU
11742         { "time(seconds)",              RLIMIT_CPU,        1, 't' },
11743 #endif
11744 #ifdef RLIMIT_FSIZE
11745         { "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
11746 #endif
11747 #ifdef RLIMIT_DATA
11748         { "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
11749 #endif
11750 #ifdef RLIMIT_STACK
11751         { "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
11752 #endif
11753 #ifdef  RLIMIT_CORE
11754         { "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
11755 #endif
11756 #ifdef RLIMIT_RSS
11757         { "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
11758 #endif
11759 #ifdef RLIMIT_MEMLOCK
11760         { "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
11761 #endif
11762 #ifdef RLIMIT_NPROC
11763         { "process",                    RLIMIT_NPROC,      1, 'p' },
11764 #endif
11765 #ifdef RLIMIT_NOFILE
11766         { "nofiles",                    RLIMIT_NOFILE,     1, 'n' },
11767 #endif
11768 #ifdef RLIMIT_AS
11769         { "vmemory(kbytes)",            RLIMIT_AS,      1024, 'v' },
11770 #endif
11771 #ifdef RLIMIT_LOCKS
11772         { "locks",                      RLIMIT_LOCKS,      1, 'w' },
11773 #endif
11774         { NULL,                         0,                 0,  '\0' }
11775 };
11776
11777 enum limtype { SOFT = 0x1, HARD = 0x2 };
11778
11779 static void
11780 printlim(enum limtype how, const struct rlimit *limit,
11781                         const struct limits *l)
11782 {
11783         rlim_t val;
11784
11785         val = limit->rlim_max;
11786         if (how & SOFT)
11787                 val = limit->rlim_cur;
11788
11789         if (val == RLIM_INFINITY)
11790                 out1fmt("unlimited\n");
11791         else {
11792                 val /= l->factor;
11793                 out1fmt("%lld\n", (long long) val);
11794         }
11795 }
11796
11797 static int
11798 ulimitcmd(int argc, char **argv)
11799 {
11800         int c;
11801         rlim_t val = 0;
11802         enum limtype how = SOFT | HARD;
11803         const struct limits *l;
11804         int set, all = 0;
11805         int optc, what;
11806         struct rlimit limit;
11807
11808         what = 'f';
11809         while ((optc = nextopt("HSa"
11810 #ifdef RLIMIT_CPU
11811                                 "t"
11812 #endif
11813 #ifdef RLIMIT_FSIZE
11814                                 "f"
11815 #endif
11816 #ifdef RLIMIT_DATA
11817                                 "d"
11818 #endif
11819 #ifdef RLIMIT_STACK
11820                                 "s"
11821 #endif
11822 #ifdef RLIMIT_CORE
11823                                 "c"
11824 #endif
11825 #ifdef RLIMIT_RSS
11826                                 "m"
11827 #endif
11828 #ifdef RLIMIT_MEMLOCK
11829                                 "l"
11830 #endif
11831 #ifdef RLIMIT_NPROC
11832                                 "p"
11833 #endif
11834 #ifdef RLIMIT_NOFILE
11835                                 "n"
11836 #endif
11837 #ifdef RLIMIT_AS
11838                                 "v"
11839 #endif
11840 #ifdef RLIMIT_LOCKS
11841                                 "w"
11842 #endif
11843                                         )) != '\0')
11844                 switch (optc) {
11845                 case 'H':
11846                         how = HARD;
11847                         break;
11848                 case 'S':
11849                         how = SOFT;
11850                         break;
11851                 case 'a':
11852                         all = 1;
11853                         break;
11854                 default:
11855                         what = optc;
11856                 }
11857
11858         for (l = limits; l->option != what; l++)
11859                 ;
11860
11861         set = *argptr ? 1 : 0;
11862         if (set) {
11863                 char *p = *argptr;
11864
11865                 if (all || argptr[1])
11866                         ash_msg_and_raise_error("too many arguments");
11867                 if (strncmp(p, "unlimited\n", 9) == 0)
11868                         val = RLIM_INFINITY;
11869                 else {
11870                         val = (rlim_t) 0;
11871
11872                         while ((c = *p++) >= '0' && c <= '9') {
11873                                 val = (val * 10) + (long)(c - '0');
11874                                 if (val < (rlim_t) 0)
11875                                         break;
11876                         }
11877                         if (c)
11878                                 ash_msg_and_raise_error("bad number");
11879                         val *= l->factor;
11880                 }
11881         }
11882         if (all) {
11883                 for (l = limits; l->name; l++) {
11884                         getrlimit(l->cmd, &limit);
11885                         out1fmt("%-20s ", l->name);
11886                         printlim(how, &limit, l);
11887                 }
11888                 return 0;
11889         }
11890
11891         getrlimit(l->cmd, &limit);
11892         if (set) {
11893                 if (how & HARD)
11894                         limit.rlim_max = val;
11895                 if (how & SOFT)
11896                         limit.rlim_cur = val;
11897                 if (setrlimit(l->cmd, &limit) < 0)
11898                         ash_msg_and_raise_error("error setting limit (%m)");
11899         } else {
11900                 printlim(how, &limit, l);
11901         }
11902         return 0;
11903 }
11904
11905
11906 /* ============ Math support */
11907
11908 #if ENABLE_ASH_MATH_SUPPORT
11909
11910 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
11911
11912    Permission is hereby granted, free of charge, to any person obtaining
11913    a copy of this software and associated documentation files (the
11914    "Software"), to deal in the Software without restriction, including
11915    without limitation the rights to use, copy, modify, merge, publish,
11916    distribute, sublicense, and/or sell copies of the Software, and to
11917    permit persons to whom the Software is furnished to do so, subject to
11918    the following conditions:
11919
11920    The above copyright notice and this permission notice shall be
11921    included in all copies or substantial portions of the Software.
11922
11923    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11924    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11925    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11926    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
11927    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11928    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11929    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11930 */
11931
11932 /* This is my infix parser/evaluator. It is optimized for size, intended
11933  * as a replacement for yacc-based parsers. However, it may well be faster
11934  * than a comparable parser written in yacc. The supported operators are
11935  * listed in #defines below. Parens, order of operations, and error handling
11936  * are supported. This code is thread safe. The exact expression format should
11937  * be that which POSIX specifies for shells. */
11938
11939 /* The code uses a simple two-stack algorithm. See
11940  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
11941  * for a detailed explanation of the infix-to-postfix algorithm on which
11942  * this is based (this code differs in that it applies operators immediately
11943  * to the stack instead of adding them to a queue to end up with an
11944  * expression). */
11945
11946 /* To use the routine, call it with an expression string and error return
11947  * pointer */
11948
11949 /*
11950  * Aug 24, 2001              Manuel Novoa III
11951  *
11952  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
11953  *
11954  * 1) In arith_apply():
11955  *    a) Cached values of *numptr and &(numptr[-1]).
11956  *    b) Removed redundant test for zero denominator.
11957  *
11958  * 2) In arith():
11959  *    a) Eliminated redundant code for processing operator tokens by moving
11960  *       to a table-based implementation.  Also folded handling of parens
11961  *       into the table.
11962  *    b) Combined all 3 loops which called arith_apply to reduce generated
11963  *       code size at the cost of speed.
11964  *
11965  * 3) The following expressions were treated as valid by the original code:
11966  *       1()  ,    0!  ,    1 ( *3 )   .
11967  *    These bugs have been fixed by internally enclosing the expression in
11968  *    parens and then checking that all binary ops and right parens are
11969  *    preceded by a valid expression (NUM_TOKEN).
11970  *
11971  * Note: It may be desirable to replace Aaron's test for whitespace with
11972  * ctype's isspace() if it is used by another busybox applet or if additional
11973  * whitespace chars should be considered.  Look below the "#include"s for a
11974  * precompiler test.
11975  */
11976
11977 /*
11978  * Aug 26, 2001              Manuel Novoa III
11979  *
11980  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
11981  *
11982  * Merge in Aaron's comments previously posted to the busybox list,
11983  * modified slightly to take account of my changes to the code.
11984  *
11985  */
11986
11987 /*
11988  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11989  *
11990  * - allow access to variable,
11991  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
11992  * - realize assign syntax (VAR=expr, +=, *= etc)
11993  * - realize exponentiation (** operator)
11994  * - realize comma separated - expr, expr
11995  * - realise ++expr --expr expr++ expr--
11996  * - realise expr ? expr : expr (but, second expr calculate always)
11997  * - allow hexadecimal and octal numbers
11998  * - was restored loses XOR operator
11999  * - remove one goto label, added three ;-)
12000  * - protect $((num num)) as true zero expr (Manuel`s error)
12001  * - always use special isspace(), see comment from bash ;-)
12002  */
12003
12004 #define arith_isspace(arithval) \
12005         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12006
12007 typedef unsigned char operator;
12008
12009 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12010  * precedence, and 3 high bits are an ID unique across operators of that
12011  * precedence. The ID portion is so that multiple operators can have the
12012  * same precedence, ensuring that the leftmost one is evaluated first.
12013  * Consider * and /. */
12014
12015 #define tok_decl(prec,id) (((id)<<5)|(prec))
12016 #define PREC(op) ((op) & 0x1F)
12017
12018 #define TOK_LPAREN tok_decl(0,0)
12019
12020 #define TOK_COMMA tok_decl(1,0)
12021
12022 #define TOK_ASSIGN tok_decl(2,0)
12023 #define TOK_AND_ASSIGN tok_decl(2,1)
12024 #define TOK_OR_ASSIGN tok_decl(2,2)
12025 #define TOK_XOR_ASSIGN tok_decl(2,3)
12026 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12027 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12028 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12029 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12030
12031 #define TOK_MUL_ASSIGN tok_decl(3,0)
12032 #define TOK_DIV_ASSIGN tok_decl(3,1)
12033 #define TOK_REM_ASSIGN tok_decl(3,2)
12034
12035 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12036 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12037
12038 /* conditional is right associativity too */
12039 #define TOK_CONDITIONAL tok_decl(4,0)
12040 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12041
12042 #define TOK_OR tok_decl(5,0)
12043
12044 #define TOK_AND tok_decl(6,0)
12045
12046 #define TOK_BOR tok_decl(7,0)
12047
12048 #define TOK_BXOR tok_decl(8,0)
12049
12050 #define TOK_BAND tok_decl(9,0)
12051
12052 #define TOK_EQ tok_decl(10,0)
12053 #define TOK_NE tok_decl(10,1)
12054
12055 #define TOK_LT tok_decl(11,0)
12056 #define TOK_GT tok_decl(11,1)
12057 #define TOK_GE tok_decl(11,2)
12058 #define TOK_LE tok_decl(11,3)
12059
12060 #define TOK_LSHIFT tok_decl(12,0)
12061 #define TOK_RSHIFT tok_decl(12,1)
12062
12063 #define TOK_ADD tok_decl(13,0)
12064 #define TOK_SUB tok_decl(13,1)
12065
12066 #define TOK_MUL tok_decl(14,0)
12067 #define TOK_DIV tok_decl(14,1)
12068 #define TOK_REM tok_decl(14,2)
12069
12070 /* exponent is right associativity */
12071 #define TOK_EXPONENT tok_decl(15,1)
12072
12073 /* For now unary operators. */
12074 #define UNARYPREC 16
12075 #define TOK_BNOT tok_decl(UNARYPREC,0)
12076 #define TOK_NOT tok_decl(UNARYPREC,1)
12077
12078 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12079 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12080
12081 #define PREC_PRE (UNARYPREC+2)
12082
12083 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12084 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12085
12086 #define PREC_POST (UNARYPREC+3)
12087
12088 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12089 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12090
12091 #define SPEC_PREC (UNARYPREC+4)
12092
12093 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12094 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12095
12096 #define NUMPTR (*numstackptr)
12097
12098 static int
12099 tok_have_assign(operator op)
12100 {
12101         operator prec = PREC(op);
12102
12103         convert_prec_is_assing(prec);
12104         return (prec == PREC(TOK_ASSIGN) ||
12105                         prec == PREC_PRE || prec == PREC_POST);
12106 }
12107
12108 static int
12109 is_right_associativity(operator prec)
12110 {
12111         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12112                 || prec == PREC(TOK_CONDITIONAL));
12113 }
12114
12115 typedef struct ARITCH_VAR_NUM {
12116         arith_t val;
12117         arith_t contidional_second_val;
12118         char contidional_second_val_initialized;
12119         char *var;      /* if NULL then is regular number,
12120                            else is variable name */
12121 } v_n_t;
12122
12123 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12124         const char *var;
12125         struct CHK_VAR_RECURSIVE_LOOPED *next;
12126 } chk_var_recursive_looped_t;
12127
12128 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12129
12130 static int
12131 arith_lookup_val(v_n_t *t)
12132 {
12133         if (t->var) {
12134                 const char * p = lookupvar(t->var);
12135
12136                 if (p) {
12137                         int errcode;
12138
12139                         /* recursive try as expression */
12140                         chk_var_recursive_looped_t *cur;
12141                         chk_var_recursive_looped_t cur_save;
12142
12143                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12144                                 if (strcmp(cur->var, t->var) == 0) {
12145                                         /* expression recursion loop detected */
12146                                         return -5;
12147                                 }
12148                         }
12149                         /* save current lookuped var name */
12150                         cur = prev_chk_var_recursive;
12151                         cur_save.var = t->var;
12152                         cur_save.next = cur;
12153                         prev_chk_var_recursive = &cur_save;
12154
12155                         t->val = arith (p, &errcode);
12156                         /* restore previous ptr after recursiving */
12157                         prev_chk_var_recursive = cur;
12158                         return errcode;
12159                 }
12160                 /* allow undefined var as 0 */
12161                 t->val = 0;
12162         }
12163         return 0;
12164 }
12165
12166 /* "applying" a token means performing it on the top elements on the integer
12167  * stack. For a unary operator it will only change the top element, but a
12168  * binary operator will pop two arguments and push a result */
12169 static int
12170 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12171 {
12172         v_n_t *numptr_m1;
12173         arith_t numptr_val, rez;
12174         int ret_arith_lookup_val;
12175
12176         /* There is no operator that can work without arguments */
12177         if (NUMPTR == numstack) goto err;
12178         numptr_m1 = NUMPTR - 1;
12179
12180         /* check operand is var with noninteger value */
12181         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12182         if (ret_arith_lookup_val)
12183                 return ret_arith_lookup_val;
12184
12185         rez = numptr_m1->val;
12186         if (op == TOK_UMINUS)
12187                 rez *= -1;
12188         else if (op == TOK_NOT)
12189                 rez = !rez;
12190         else if (op == TOK_BNOT)
12191                 rez = ~rez;
12192         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12193                 rez++;
12194         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12195                 rez--;
12196         else if (op != TOK_UPLUS) {
12197                 /* Binary operators */
12198
12199                 /* check and binary operators need two arguments */
12200                 if (numptr_m1 == numstack) goto err;
12201
12202                 /* ... and they pop one */
12203                 --NUMPTR;
12204                 numptr_val = rez;
12205                 if (op == TOK_CONDITIONAL) {
12206                         if (! numptr_m1->contidional_second_val_initialized) {
12207                                 /* protect $((expr1 ? expr2)) without ": expr" */
12208                                 goto err;
12209                         }
12210                         rez = numptr_m1->contidional_second_val;
12211                 } else if (numptr_m1->contidional_second_val_initialized) {
12212                         /* protect $((expr1 : expr2)) without "expr ? " */
12213                         goto err;
12214                 }
12215                 numptr_m1 = NUMPTR - 1;
12216                 if (op != TOK_ASSIGN) {
12217                         /* check operand is var with noninteger value for not '=' */
12218                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12219                         if (ret_arith_lookup_val)
12220                                 return ret_arith_lookup_val;
12221                 }
12222                 if (op == TOK_CONDITIONAL) {
12223                         numptr_m1->contidional_second_val = rez;
12224                 }
12225                 rez = numptr_m1->val;
12226                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12227                         rez |= numptr_val;
12228                 else if (op == TOK_OR)
12229                         rez = numptr_val || rez;
12230                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12231                         rez &= numptr_val;
12232                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12233                         rez ^= numptr_val;
12234                 else if (op == TOK_AND)
12235                         rez = rez && numptr_val;
12236                 else if (op == TOK_EQ)
12237                         rez = (rez == numptr_val);
12238                 else if (op == TOK_NE)
12239                         rez = (rez != numptr_val);
12240                 else if (op == TOK_GE)
12241                         rez = (rez >= numptr_val);
12242                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12243                         rez >>= numptr_val;
12244                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12245                         rez <<= numptr_val;
12246                 else if (op == TOK_GT)
12247                         rez = (rez > numptr_val);
12248                 else if (op == TOK_LT)
12249                         rez = (rez < numptr_val);
12250                 else if (op == TOK_LE)
12251                         rez = (rez <= numptr_val);
12252                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12253                         rez *= numptr_val;
12254                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12255                         rez += numptr_val;
12256                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12257                         rez -= numptr_val;
12258                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12259                         rez = numptr_val;
12260                 else if (op == TOK_CONDITIONAL_SEP) {
12261                         if (numptr_m1 == numstack) {
12262                                 /* protect $((expr : expr)) without "expr ? " */
12263                                 goto err;
12264                         }
12265                         numptr_m1->contidional_second_val_initialized = op;
12266                         numptr_m1->contidional_second_val = numptr_val;
12267                 } else if (op == TOK_CONDITIONAL) {
12268                         rez = rez ?
12269                                 numptr_val : numptr_m1->contidional_second_val;
12270                 } else if (op == TOK_EXPONENT) {
12271                         if (numptr_val < 0)
12272                                 return -3;      /* exponent less than 0 */
12273                         else {
12274                                 arith_t c = 1;
12275
12276                                 if (numptr_val)
12277                                         while (numptr_val--)
12278                                                 c *= rez;
12279                                 rez = c;
12280                         }
12281                 } else if (numptr_val==0)          /* zero divisor check */
12282                         return -2;
12283                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12284                         rez /= numptr_val;
12285                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12286                         rez %= numptr_val;
12287         }
12288         if (tok_have_assign(op)) {
12289                 char buf[sizeof(arith_t_type)*3 + 2];
12290
12291                 if (numptr_m1->var == NULL) {
12292                         /* Hmm, 1=2 ? */
12293                         goto err;
12294                 }
12295                 /* save to shell variable */
12296 #if ENABLE_ASH_MATH_SUPPORT_64
12297                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12298 #else
12299                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12300 #endif
12301                 setvar(numptr_m1->var, buf, 0);
12302                 /* after saving, make previous value for v++ or v-- */
12303                 if (op == TOK_POST_INC)
12304                         rez--;
12305                 else if (op == TOK_POST_DEC)
12306                         rez++;
12307         }
12308         numptr_m1->val = rez;
12309         /* protect geting var value, is number now */
12310         numptr_m1->var = NULL;
12311         return 0;
12312  err:
12313         return -1;
12314 }
12315
12316 /* longest must be first */
12317 static const char op_tokens[] = {
12318         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12319         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12320         '<','<',    0, TOK_LSHIFT,
12321         '>','>',    0, TOK_RSHIFT,
12322         '|','|',    0, TOK_OR,
12323         '&','&',    0, TOK_AND,
12324         '!','=',    0, TOK_NE,
12325         '<','=',    0, TOK_LE,
12326         '>','=',    0, TOK_GE,
12327         '=','=',    0, TOK_EQ,
12328         '|','=',    0, TOK_OR_ASSIGN,
12329         '&','=',    0, TOK_AND_ASSIGN,
12330         '*','=',    0, TOK_MUL_ASSIGN,
12331         '/','=',    0, TOK_DIV_ASSIGN,
12332         '%','=',    0, TOK_REM_ASSIGN,
12333         '+','=',    0, TOK_PLUS_ASSIGN,
12334         '-','=',    0, TOK_MINUS_ASSIGN,
12335         '-','-',    0, TOK_POST_DEC,
12336         '^','=',    0, TOK_XOR_ASSIGN,
12337         '+','+',    0, TOK_POST_INC,
12338         '*','*',    0, TOK_EXPONENT,
12339         '!',        0, TOK_NOT,
12340         '<',        0, TOK_LT,
12341         '>',        0, TOK_GT,
12342         '=',        0, TOK_ASSIGN,
12343         '|',        0, TOK_BOR,
12344         '&',        0, TOK_BAND,
12345         '*',        0, TOK_MUL,
12346         '/',        0, TOK_DIV,
12347         '%',        0, TOK_REM,
12348         '+',        0, TOK_ADD,
12349         '-',        0, TOK_SUB,
12350         '^',        0, TOK_BXOR,
12351         /* uniq */
12352         '~',        0, TOK_BNOT,
12353         ',',        0, TOK_COMMA,
12354         '?',        0, TOK_CONDITIONAL,
12355         ':',        0, TOK_CONDITIONAL_SEP,
12356         ')',        0, TOK_RPAREN,
12357         '(',        0, TOK_LPAREN,
12358         0
12359 };
12360 /* ptr to ")" */
12361 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12362
12363 static arith_t
12364 arith(const char *expr, int *perrcode)
12365 {
12366         char arithval; /* Current character under analysis */
12367         operator lasttok, op;
12368         operator prec;
12369
12370         const char *p = endexpression;
12371         int errcode;
12372
12373         size_t datasizes = strlen(expr) + 2;
12374
12375         /* Stack of integers */
12376         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12377          * in any given correct or incorrect expression is left as an exercise to
12378          * the reader. */
12379         v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12380                                 *numstackptr = numstack;
12381         /* Stack of operator tokens */
12382         operator *stack = alloca((datasizes) * sizeof(operator)),
12383                                 *stackptr = stack;
12384
12385         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
12386         *perrcode = errcode = 0;
12387
12388         while (1) {
12389                 arithval = *expr;
12390                 if (arithval == 0) {
12391                         if (p == endexpression) {
12392                                 /* Null expression. */
12393                                 return 0;
12394                         }
12395
12396                         /* This is only reached after all tokens have been extracted from the
12397                          * input stream. If there are still tokens on the operator stack, they
12398                          * are to be applied in order. At the end, there should be a final
12399                          * result on the integer stack */
12400
12401                         if (expr != endexpression + 1) {
12402                                 /* If we haven't done so already, */
12403                                 /* append a closing right paren */
12404                                 expr = endexpression;
12405                                 /* and let the loop process it. */
12406                                 continue;
12407                         }
12408                         /* At this point, we're done with the expression. */
12409                         if (numstackptr != numstack+1) {
12410                                 /* ... but if there isn't, it's bad */
12411  err:
12412                                 return (*perrcode = -1);
12413                         }
12414                         if (numstack->var) {
12415                                 /* expression is $((var)) only, lookup now */
12416                                 errcode = arith_lookup_val(numstack);
12417                         }
12418  ret:
12419                         *perrcode = errcode;
12420                         return numstack->val;
12421                 }
12422
12423                 /* Continue processing the expression. */
12424                 if (arith_isspace(arithval)) {
12425                         /* Skip whitespace */
12426                         goto prologue;
12427                 }
12428                 p = endofname(expr);
12429                 if (p != expr) {
12430                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
12431
12432                         numstackptr->var = alloca(var_name_size);
12433                         safe_strncpy(numstackptr->var, expr, var_name_size);
12434                         expr = p;
12435  num:
12436                         numstackptr->contidional_second_val_initialized = 0;
12437                         numstackptr++;
12438                         lasttok = TOK_NUM;
12439                         continue;
12440                 }
12441                 if (isdigit(arithval)) {
12442                         numstackptr->var = NULL;
12443 #if ENABLE_ASH_MATH_SUPPORT_64
12444                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
12445 #else
12446                         numstackptr->val = strtol(expr, (char **) &expr, 0);
12447 #endif
12448                         goto num;
12449                 }
12450                 for (p = op_tokens; ; p++) {
12451                         const char *o;
12452
12453                         if (*p == 0) {
12454                                 /* strange operator not found */
12455                                 goto err;
12456                         }
12457                         for (o = expr; *p && *o == *p; p++)
12458                                 o++;
12459                         if (! *p) {
12460                                 /* found */
12461                                 expr = o - 1;
12462                                 break;
12463                         }
12464                         /* skip tail uncompared token */
12465                         while (*p)
12466                                 p++;
12467                         /* skip zero delim */
12468                         p++;
12469                 }
12470                 op = p[1];
12471
12472                 /* post grammar: a++ reduce to num */
12473                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12474                         lasttok = TOK_NUM;
12475
12476                 /* Plus and minus are binary (not unary) _only_ if the last
12477                  * token was as number, or a right paren (which pretends to be
12478                  * a number, since it evaluates to one). Think about it.
12479                  * It makes sense. */
12480                 if (lasttok != TOK_NUM) {
12481                         switch (op) {
12482                         case TOK_ADD:
12483                                 op = TOK_UPLUS;
12484                                 break;
12485                         case TOK_SUB:
12486                                 op = TOK_UMINUS;
12487                                 break;
12488                         case TOK_POST_INC:
12489                                 op = TOK_PRE_INC;
12490                                 break;
12491                         case TOK_POST_DEC:
12492                                 op = TOK_PRE_DEC;
12493                                 break;
12494                         }
12495                 }
12496                 /* We don't want a unary operator to cause recursive descent on the
12497                  * stack, because there can be many in a row and it could cause an
12498                  * operator to be evaluated before its argument is pushed onto the
12499                  * integer stack. */
12500                 /* But for binary operators, "apply" everything on the operator
12501                  * stack until we find an operator with a lesser priority than the
12502                  * one we have just extracted. */
12503                 /* Left paren is given the lowest priority so it will never be
12504                  * "applied" in this way.
12505                  * if associativity is right and priority eq, applied also skip
12506                  */
12507                 prec = PREC(op);
12508                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12509                         /* not left paren or unary */
12510                         if (lasttok != TOK_NUM) {
12511                                 /* binary op must be preceded by a num */
12512                                 goto err;
12513                         }
12514                         while (stackptr != stack) {
12515                                 if (op == TOK_RPAREN) {
12516                                         /* The algorithm employed here is simple: while we don't
12517                                          * hit an open paren nor the bottom of the stack, pop
12518                                          * tokens and apply them */
12519                                         if (stackptr[-1] == TOK_LPAREN) {
12520                                                 --stackptr;
12521                                                 /* Any operator directly after a */
12522                                                 lasttok = TOK_NUM;
12523                                                 /* close paren should consider itself binary */
12524                                                 goto prologue;
12525                                         }
12526                                 } else {
12527                                         operator prev_prec = PREC(stackptr[-1]);
12528
12529                                         convert_prec_is_assing(prec);
12530                                         convert_prec_is_assing(prev_prec);
12531                                         if (prev_prec < prec)
12532                                                 break;
12533                                         /* check right assoc */
12534                                         if (prev_prec == prec && is_right_associativity(prec))
12535                                                 break;
12536                                 }
12537                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12538                                 if (errcode) goto ret;
12539                         }
12540                         if (op == TOK_RPAREN) {
12541                                 goto err;
12542                         }
12543                 }
12544
12545                 /* Push this operator to the stack and remember it. */
12546                 *stackptr++ = lasttok = op;
12547  prologue:
12548                 ++expr;
12549         } /* while */
12550 }
12551 #endif /* ASH_MATH_SUPPORT */
12552
12553
12554 /* ============ main() and helpers */
12555
12556 /*
12557  * Called to exit the shell.
12558  */
12559 static void exitshell(void) ATTRIBUTE_NORETURN;
12560 static void
12561 exitshell(void)
12562 {
12563         struct jmploc loc;
12564         char *p;
12565         int status;
12566
12567         status = exitstatus;
12568         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12569         if (setjmp(loc.loc)) {
12570                 if (exception == EXEXIT)
12571 /* dash bug: it just does _exit(exitstatus) here
12572  * but we have to do setjobctl(0) first!
12573  * (bug is still not fixed in dash-0.5.3 - if you run dash
12574  * under Midnight Commander, on exit from dash MC is backgrounded) */
12575                         status = exitstatus;
12576                 goto out;
12577         }
12578         exception_handler = &loc;
12579         p = trap[0];
12580         if (p) {
12581                 trap[0] = NULL;
12582                 evalstring(p, 0);
12583         }
12584         flush_stdout_stderr();
12585  out:
12586         setjobctl(0);
12587         _exit(status);
12588         /* NOTREACHED */
12589 }
12590
12591 static void
12592 init(void)
12593 {
12594         /* from input.c: */
12595         basepf.nextc = basepf.buf = basebuf;
12596
12597         /* from trap.c: */
12598         signal(SIGCHLD, SIG_DFL);
12599
12600         /* from var.c: */
12601         {
12602                 char **envp;
12603                 char ppid[sizeof(int)*3 + 1];
12604                 const char *p;
12605                 struct stat st1, st2;
12606
12607                 initvar();
12608                 for (envp = environ; envp && *envp; envp++) {
12609                         if (strchr(*envp, '=')) {
12610                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12611                         }
12612                 }
12613
12614                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12615                 setvar("PPID", ppid, 0);
12616
12617                 p = lookupvar("PWD");
12618                 if (p)
12619                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12620                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12621                                 p = '\0';
12622                 setpwd(p, 0);
12623         }
12624 }
12625
12626 /*
12627  * Process the shell command line arguments.
12628  */
12629 static void
12630 procargs(int argc, char **argv)
12631 {
12632         int i;
12633         const char *xminusc;
12634         char **xargv;
12635
12636         xargv = argv;
12637         arg0 = xargv[0];
12638         if (argc > 0)
12639                 xargv++;
12640         for (i = 0; i < NOPTS; i++)
12641                 optlist[i] = 2;
12642         argptr = xargv;
12643         options(1);
12644         xargv = argptr;
12645         xminusc = minusc;
12646         if (*xargv == NULL) {
12647                 if (xminusc)
12648                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12649                 sflag = 1;
12650         }
12651         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12652                 iflag = 1;
12653         if (mflag == 2)
12654                 mflag = iflag;
12655         for (i = 0; i < NOPTS; i++)
12656                 if (optlist[i] == 2)
12657                         optlist[i] = 0;
12658 #if DEBUG == 2
12659         debug = 1;
12660 #endif
12661         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12662         if (xminusc) {
12663                 minusc = *xargv++;
12664                 if (*xargv)
12665                         goto setarg0;
12666         } else if (!sflag) {
12667                 setinputfile(*xargv, 0);
12668  setarg0:
12669                 arg0 = *xargv++;
12670                 commandname = arg0;
12671         }
12672
12673         shellparam.p = xargv;
12674 #if ENABLE_ASH_GETOPTS
12675         shellparam.optind = 1;
12676         shellparam.optoff = -1;
12677 #endif
12678         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12679         while (*xargv) {
12680                 shellparam.nparam++;
12681                 xargv++;
12682         }
12683         optschanged();
12684 }
12685
12686 /*
12687  * Read /etc/profile or .profile.
12688  */
12689 static void
12690 read_profile(const char *name)
12691 {
12692         int skip;
12693
12694         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12695                 return;
12696         skip = cmdloop(0);
12697         popfile();
12698         if (skip)
12699                 exitshell();
12700 }
12701
12702 /*
12703  * This routine is called when an error or an interrupt occurs in an
12704  * interactive shell and control is returned to the main command loop.
12705  */
12706 static void
12707 reset(void)
12708 {
12709         /* from eval.c: */
12710         evalskip = 0;
12711         loopnest = 0;
12712         /* from input.c: */
12713         parselleft = parsenleft = 0;      /* clear input buffer */
12714         popallfiles();
12715         /* from parser.c: */
12716         tokpushback = 0;
12717         checkkwd = 0;
12718         /* from redir.c: */
12719         clearredir(0);
12720 }
12721
12722 #if PROFILE
12723 static short profile_buf[16384];
12724 extern int etext();
12725 #endif
12726
12727 /*
12728  * Main routine.  We initialize things, parse the arguments, execute
12729  * profiles if we're a login shell, and then call cmdloop to execute
12730  * commands.  The setjmp call sets up the location to jump to when an
12731  * exception occurs.  When an exception occurs the variable "state"
12732  * is used to figure out how far we had gotten.
12733  */
12734 int ash_main(int argc, char **argv);
12735 int ash_main(int argc, char **argv)
12736 {
12737         char *shinit;
12738         volatile int state;
12739         struct jmploc jmploc;
12740         struct stackmark smark;
12741
12742 #ifdef __GLIBC__
12743         dash_errno = __errno_location();
12744 #endif
12745
12746 #if PROFILE
12747         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12748 #endif
12749
12750 #if ENABLE_FEATURE_EDITING
12751         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12752 #endif
12753         state = 0;
12754         if (setjmp(jmploc.loc)) {
12755                 int e;
12756                 int s;
12757
12758                 reset();
12759
12760                 e = exception;
12761                 if (e == EXERROR)
12762                         exitstatus = 2;
12763                 s = state;
12764                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12765                         exitshell();
12766
12767                 if (e == EXINT) {
12768                         outcslow('\n', stderr);
12769                 }
12770                 popstackmark(&smark);
12771                 FORCE_INT_ON; /* enable interrupts */
12772                 if (s == 1)
12773                         goto state1;
12774                 if (s == 2)
12775                         goto state2;
12776                 if (s == 3)
12777                         goto state3;
12778                 goto state4;
12779         }
12780         exception_handler = &jmploc;
12781 #if DEBUG
12782         opentrace();
12783         trace_puts("Shell args: ");
12784         trace_puts_args(argv);
12785 #endif
12786         rootpid = getpid();
12787
12788 #if ENABLE_ASH_RANDOM_SUPPORT
12789         rseed = rootpid + time(NULL);
12790 #endif
12791         init();
12792         setstackmark(&smark);
12793         procargs(argc, argv);
12794 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12795         if (iflag) {
12796                 const char *hp = lookupvar("HISTFILE");
12797
12798                 if (hp == NULL) {
12799                         hp = lookupvar("HOME");
12800                         if (hp != NULL) {
12801                                 char *defhp = concat_path_file(hp, ".ash_history");
12802                                 setvar("HISTFILE", defhp, 0);
12803                                 free(defhp);
12804                         }
12805                 }
12806         }
12807 #endif
12808         if (argv[0] && argv[0][0] == '-')
12809                 isloginsh = 1;
12810         if (isloginsh) {
12811                 state = 1;
12812                 read_profile("/etc/profile");
12813  state1:
12814                 state = 2;
12815                 read_profile(".profile");
12816         }
12817  state2:
12818         state = 3;
12819         if (
12820 #ifndef linux
12821          getuid() == geteuid() && getgid() == getegid() &&
12822 #endif
12823          iflag
12824         ) {
12825                 shinit = lookupvar("ENV");
12826                 if (shinit != NULL && *shinit != '\0') {
12827                         read_profile(shinit);
12828                 }
12829         }
12830  state3:
12831         state = 4;
12832         if (minusc)
12833                 evalstring(minusc, 0);
12834
12835         if (sflag || minusc == NULL) {
12836 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12837                 if ( iflag ) {
12838                         const char *hp = lookupvar("HISTFILE");
12839
12840                         if (hp != NULL)
12841                                 line_input_state->hist_file = hp;
12842                 }
12843 #endif
12844  state4: /* XXX ??? - why isn't this before the "if" statement */
12845                 cmdloop(1);
12846         }
12847 #if PROFILE
12848         monitor(0);
12849 #endif
12850 #ifdef GPROF
12851         {
12852                 extern void _mcleanup(void);
12853                 _mcleanup();
12854         }
12855 #endif
12856         exitshell();
12857         /* NOTREACHED */
12858 }
12859
12860 #if DEBUG
12861 const char *applet_name = "debug stuff usage";
12862 int main(int argc, char **argv)
12863 {
12864         return ash_main(argc, argv);
12865 }
12866 #endif
12867
12868
12869 /*-
12870  * Copyright (c) 1989, 1991, 1993, 1994
12871  *      The Regents of the University of California.  All rights reserved.
12872  *
12873  * This code is derived from software contributed to Berkeley by
12874  * Kenneth Almquist.
12875  *
12876  * Redistribution and use in source and binary forms, with or without
12877  * modification, are permitted provided that the following conditions
12878  * are met:
12879  * 1. Redistributions of source code must retain the above copyright
12880  *    notice, this list of conditions and the following disclaimer.
12881  * 2. Redistributions in binary form must reproduce the above copyright
12882  *    notice, this list of conditions and the following disclaimer in the
12883  *    documentation and/or other materials provided with the distribution.
12884  * 3. Neither the name of the University nor the names of its contributors
12885  *    may be used to endorse or promote products derived from this software
12886  *    without specific prior written permission.
12887  *
12888  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12889  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12890  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12891  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12892  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12893  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12894  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12895  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12896  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12897  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12898  * SUCH DAMAGE.
12899  */