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