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