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