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