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