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