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