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