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