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