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