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