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