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