ash: shrink on top of previous change
[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 *prev_string;
1037         int prev_left_in_line;
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 left_in_line;       /* number of chars left in this line */
1049         int left_in_buffer;     /* number of chars left in this buffer past the line */
1050         char *next_to_pgetc;    /* 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 enum {
9083         INPUT_PUSH_FILE = 1,
9084         INPUT_NOFILE_OK = 2,
9085 };
9086
9087 static smallint checkkwd;
9088 /* values of checkkwd variable */
9089 #define CHKALIAS        0x1
9090 #define CHKKWD          0x2
9091 #define CHKNL           0x4
9092
9093 /*
9094  * Push a string back onto the input at this current parsefile level.
9095  * We handle aliases this way.
9096  */
9097 #if !ENABLE_ASH_ALIAS
9098 #define pushstring(s, ap) pushstring(s)
9099 #endif
9100 static void
9101 pushstring(char *s, struct alias *ap)
9102 {
9103         struct strpush *sp;
9104         int len;
9105
9106         len = strlen(s);
9107         INT_OFF;
9108         if (g_parsefile->strpush) {
9109                 sp = ckzalloc(sizeof(*sp));
9110                 sp->prev = g_parsefile->strpush;
9111         } else {
9112                 sp = &(g_parsefile->basestrpush);
9113         }
9114         g_parsefile->strpush = sp;
9115         sp->prev_string = g_parsefile->next_to_pgetc;
9116         sp->prev_left_in_line = g_parsefile->left_in_line;
9117 #if ENABLE_ASH_ALIAS
9118         sp->ap = ap;
9119         if (ap) {
9120                 ap->flag |= ALIASINUSE;
9121                 sp->string = s;
9122         }
9123 #endif
9124         g_parsefile->next_to_pgetc = s;
9125         g_parsefile->left_in_line = len;
9126         INT_ON;
9127 }
9128
9129 static void
9130 popstring(void)
9131 {
9132         struct strpush *sp = g_parsefile->strpush;
9133
9134         INT_OFF;
9135 #if ENABLE_ASH_ALIAS
9136         if (sp->ap) {
9137                 if (g_parsefile->next_to_pgetc[-1] == ' '
9138                  || g_parsefile->next_to_pgetc[-1] == '\t'
9139                 ) {
9140                         checkkwd |= CHKALIAS;
9141                 }
9142                 if (sp->string != sp->ap->val) {
9143                         free(sp->string);
9144                 }
9145                 sp->ap->flag &= ~ALIASINUSE;
9146                 if (sp->ap->flag & ALIASDEAD) {
9147                         unalias(sp->ap->name);
9148                 }
9149         }
9150 #endif
9151         g_parsefile->next_to_pgetc = sp->prev_string;
9152         g_parsefile->left_in_line = sp->prev_left_in_line;
9153         g_parsefile->strpush = sp->prev;
9154         if (sp != &(g_parsefile->basestrpush))
9155                 free(sp);
9156         INT_ON;
9157 }
9158
9159 static int
9160 preadfd(void)
9161 {
9162         int nr;
9163         char *buf = g_parsefile->buf;
9164
9165         g_parsefile->next_to_pgetc = buf;
9166 #if ENABLE_FEATURE_EDITING
9167  retry:
9168         if (!iflag || g_parsefile->fd != STDIN_FILENO)
9169                 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9170         else {
9171 #if ENABLE_FEATURE_TAB_COMPLETION
9172                 line_input_state->path_lookup = pathval();
9173 #endif
9174                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9175                 if (nr == 0) {
9176                         /* Ctrl+C pressed */
9177                         if (trap[SIGINT]) {
9178                                 buf[0] = '\n';
9179                                 buf[1] = '\0';
9180                                 raise(SIGINT);
9181                                 return 1;
9182                         }
9183                         goto retry;
9184                 }
9185                 if (nr < 0 && errno == 0) {
9186                         /* Ctrl+D pressed */
9187                         nr = 0;
9188                 }
9189         }
9190 #else
9191         nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9192 #endif
9193
9194 #if 0
9195 /* nonblock_safe_read() handles this problem */
9196         if (nr < 0) {
9197                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9198                         int flags = fcntl(0, F_GETFL);
9199                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9200                                 flags &= ~O_NONBLOCK;
9201                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9202                                         out2str("sh: turning off NDELAY mode\n");
9203                                         goto retry;
9204                                 }
9205                         }
9206                 }
9207         }
9208 #endif
9209         return nr;
9210 }
9211
9212 /*
9213  * Refill the input buffer and return the next input character:
9214  *
9215  * 1) If a string was pushed back on the input, pop it;
9216  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9217  *    or we are reading from a string so we can't refill the buffer,
9218  *    return EOF.
9219  * 3) If the is more stuff in this buffer, use it else call read to fill it.
9220  * 4) Process input up to the next newline, deleting nul characters.
9221  */
9222 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9223 #define pgetc_debug(...) ((void)0)
9224 static int
9225 preadbuffer(void)
9226 {
9227         char *q;
9228         int more;
9229
9230         while (g_parsefile->strpush) {
9231 #if ENABLE_ASH_ALIAS
9232                 if (g_parsefile->left_in_line == -1
9233                  && g_parsefile->strpush->ap
9234                  && g_parsefile->next_to_pgetc[-1] != ' '
9235                  && g_parsefile->next_to_pgetc[-1] != '\t'
9236                 ) {
9237                         pgetc_debug("preadbuffer PEOA");
9238                         return PEOA;
9239                 }
9240 #endif
9241                 popstring();
9242                 /* try "pgetc" now: */
9243                 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9244                                 g_parsefile->left_in_line,
9245                                 g_parsefile->next_to_pgetc,
9246                                 g_parsefile->next_to_pgetc);
9247                 if (--g_parsefile->left_in_line >= 0)
9248                         return (unsigned char)(*g_parsefile->next_to_pgetc++);
9249         }
9250         /* on both branches above g_parsefile->left_in_line < 0.
9251          * "pgetc" needs refilling.
9252          */
9253
9254         /* -90 is -BIGNUM. Below we use -99 to mark "EOF on read",
9255          * pungetc() may increment it a few times.
9256          * Assuming it won't increment it to 0.
9257          */
9258         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9259                 pgetc_debug("preadbuffer PEOF1");
9260                 /* even in failure keep left_in_line and next_to_pgetc
9261                  * in lock step, for correct multi-layer pungetc.
9262                  * left_in_line was decremented before preadbuffer(),
9263                  * must inc next_to_pgetc: */
9264                 g_parsefile->next_to_pgetc++;
9265                 return PEOF;
9266         }
9267
9268         more = g_parsefile->left_in_buffer;
9269         if (more <= 0) {
9270                 flush_stdout_stderr();
9271  again:
9272                 more = preadfd();
9273                 if (more <= 0) {
9274                         /* don't try reading again */
9275                         g_parsefile->left_in_line = -99;
9276                         pgetc_debug("preadbuffer PEOF2");
9277                         g_parsefile->next_to_pgetc++;
9278                         return PEOF;
9279                 }
9280         }
9281
9282         /* Find out where's the end of line.
9283          * Set g_parsefile->left_in_line
9284          * and g_parsefile->left_in_buffer acordingly.
9285          * NUL chars are deleted.
9286          */
9287         q = g_parsefile->next_to_pgetc;
9288         for (;;) {
9289                 char c;
9290
9291                 more--;
9292
9293                 c = *q;
9294                 if (c == '\0') {
9295                         memmove(q, q + 1, more);
9296                 } else {
9297                         q++;
9298                         if (c == '\n') {
9299                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9300                                 break;
9301                         }
9302                 }
9303
9304                 if (more <= 0) {
9305                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9306                         if (g_parsefile->left_in_line < 0)
9307                                 goto again;
9308                         break;
9309                 }
9310         }
9311         g_parsefile->left_in_buffer = more;
9312
9313         if (vflag) {
9314                 char save = *q;
9315                 *q = '\0';
9316                 out2str(g_parsefile->next_to_pgetc);
9317                 *q = save;
9318         }
9319
9320         pgetc_debug("preadbuffer at %d:%p'%s'",
9321                         g_parsefile->left_in_line,
9322                         g_parsefile->next_to_pgetc,
9323                         g_parsefile->next_to_pgetc);
9324         return (unsigned char)(*g_parsefile->next_to_pgetc++);
9325 }
9326
9327 #define pgetc_as_macro() \
9328         (--g_parsefile->left_in_line >= 0 \
9329         ? (unsigned char)(*g_parsefile->next_to_pgetc++) \
9330         : preadbuffer() \
9331         )
9332
9333 static int
9334 pgetc(void)
9335 {
9336         pgetc_debug("pgetc_fast at %d:%p'%s'",
9337                         g_parsefile->left_in_line,
9338                         g_parsefile->next_to_pgetc,
9339                         g_parsefile->next_to_pgetc);
9340         return pgetc_as_macro();
9341 }
9342
9343 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9344 #define pgetc_fast() pgetc()
9345 #else
9346 #define pgetc_fast() pgetc_as_macro()
9347 #endif
9348
9349 /*
9350  * Same as pgetc(), but ignores PEOA.
9351  */
9352 #if ENABLE_ASH_ALIAS
9353 static int
9354 pgetc2(void)
9355 {
9356         int c;
9357         do {
9358                 pgetc_debug("pgetc_fast at %d:%p'%s'",
9359                                 g_parsefile->left_in_line,
9360                                 g_parsefile->next_to_pgetc,
9361                                 g_parsefile->next_to_pgetc);
9362                 c = pgetc_fast();
9363         } while (c == PEOA);
9364         return c;
9365 }
9366 #else
9367 #define pgetc2() pgetc()
9368 #endif
9369
9370 /*
9371  * Read a line from the script.
9372  */
9373 static char *
9374 pfgets(char *line, int len)
9375 {
9376         char *p = line;
9377         int nleft = len;
9378         int c;
9379
9380         while (--nleft > 0) {
9381                 c = pgetc2();
9382                 if (c == PEOF) {
9383                         if (p == line)
9384                                 return NULL;
9385                         break;
9386                 }
9387                 *p++ = c;
9388                 if (c == '\n')
9389                         break;
9390         }
9391         *p = '\0';
9392         return line;
9393 }
9394
9395 /*
9396  * Undo the last call to pgetc.  Only one character may be pushed back.
9397  * PEOF may be pushed back.
9398  */
9399 static void
9400 pungetc(void)
9401 {
9402         g_parsefile->left_in_line++;
9403         g_parsefile->next_to_pgetc--;
9404         pgetc_debug("pushed back to %d:%p'%s'",
9405                         g_parsefile->left_in_line,
9406                         g_parsefile->next_to_pgetc,
9407                         g_parsefile->next_to_pgetc);
9408 }
9409
9410 /*
9411  * To handle the "." command, a stack of input files is used.  Pushfile
9412  * adds a new entry to the stack and popfile restores the previous level.
9413  */
9414 static void
9415 pushfile(void)
9416 {
9417         struct parsefile *pf;
9418
9419         pf = ckzalloc(sizeof(*pf));
9420         pf->prev = g_parsefile;
9421         pf->fd = -1;
9422         /*pf->strpush = NULL; - ckzalloc did it */
9423         /*pf->basestrpush.prev = NULL;*/
9424         g_parsefile = pf;
9425 }
9426
9427 static void
9428 popfile(void)
9429 {
9430         struct parsefile *pf = g_parsefile;
9431
9432         INT_OFF;
9433         if (pf->fd >= 0)
9434                 close(pf->fd);
9435         free(pf->buf);
9436         while (pf->strpush)
9437                 popstring();
9438         g_parsefile = pf->prev;
9439         free(pf);
9440         INT_ON;
9441 }
9442
9443 /*
9444  * Return to top level.
9445  */
9446 static void
9447 popallfiles(void)
9448 {
9449         while (g_parsefile != &basepf)
9450                 popfile();
9451 }
9452
9453 /*
9454  * Close the file(s) that the shell is reading commands from.  Called
9455  * after a fork is done.
9456  */
9457 static void
9458 closescript(void)
9459 {
9460         popallfiles();
9461         if (g_parsefile->fd > 0) {
9462                 close(g_parsefile->fd);
9463                 g_parsefile->fd = 0;
9464         }
9465 }
9466
9467 /*
9468  * Like setinputfile, but takes an open file descriptor.  Call this with
9469  * interrupts off.
9470  */
9471 static void
9472 setinputfd(int fd, int push)
9473 {
9474         close_on_exec_on(fd);
9475         if (push) {
9476                 pushfile();
9477                 g_parsefile->buf = NULL;
9478         }
9479         g_parsefile->fd = fd;
9480         if (g_parsefile->buf == NULL)
9481                 g_parsefile->buf = ckmalloc(IBUFSIZ);
9482         g_parsefile->left_in_buffer = 0;
9483         g_parsefile->left_in_line = 0;
9484         g_parsefile->linno = 1;
9485 }
9486
9487 /*
9488  * Set the input to take input from a file.  If push is set, push the
9489  * old input onto the stack first.
9490  */
9491 static int
9492 setinputfile(const char *fname, int flags)
9493 {
9494         int fd;
9495         int fd2;
9496
9497         INT_OFF;
9498         fd = open(fname, O_RDONLY);
9499         if (fd < 0) {
9500                 if (flags & INPUT_NOFILE_OK)
9501                         goto out;
9502                 ash_msg_and_raise_error("can't open %s", fname);
9503         }
9504         if (fd < 10) {
9505                 fd2 = copyfd(fd, 10);
9506                 close(fd);
9507                 if (fd2 < 0)
9508                         ash_msg_and_raise_error("out of file descriptors");
9509                 fd = fd2;
9510         }
9511         setinputfd(fd, flags & INPUT_PUSH_FILE);
9512  out:
9513         INT_ON;
9514         return fd;
9515 }
9516
9517 /*
9518  * Like setinputfile, but takes input from a string.
9519  */
9520 static void
9521 setinputstring(char *string)
9522 {
9523         INT_OFF;
9524         pushfile();
9525         g_parsefile->next_to_pgetc = string;
9526         g_parsefile->left_in_line = strlen(string);
9527         g_parsefile->buf = NULL;
9528         g_parsefile->linno = 1;
9529         INT_ON;
9530 }
9531
9532
9533 /* ============ mail.c
9534  *
9535  * Routines to check for mail.
9536  */
9537
9538 #if ENABLE_ASH_MAIL
9539
9540 #define MAXMBOXES 10
9541
9542 /* times of mailboxes */
9543 static time_t mailtime[MAXMBOXES];
9544 /* Set if MAIL or MAILPATH is changed. */
9545 static smallint mail_var_path_changed;
9546
9547 /*
9548  * Print appropriate message(s) if mail has arrived.
9549  * If mail_var_path_changed is set,
9550  * then the value of MAIL has mail_var_path_changed,
9551  * so we just update the values.
9552  */
9553 static void
9554 chkmail(void)
9555 {
9556         const char *mpath;
9557         char *p;
9558         char *q;
9559         time_t *mtp;
9560         struct stackmark smark;
9561         struct stat statb;
9562
9563         setstackmark(&smark);
9564         mpath = mpathset() ? mpathval() : mailval();
9565         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9566                 p = padvance(&mpath, nullstr);
9567                 if (p == NULL)
9568                         break;
9569                 if (*p == '\0')
9570                         continue;
9571                 for (q = p; *q; q++)
9572                         continue;
9573 #if DEBUG
9574                 if (q[-1] != '/')
9575                         abort();
9576 #endif
9577                 q[-1] = '\0';                   /* delete trailing '/' */
9578                 if (stat(p, &statb) < 0) {
9579                         *mtp = 0;
9580                         continue;
9581                 }
9582                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9583                         fprintf(
9584                                 stderr, snlfmt,
9585                                 pathopt ? pathopt : "you have mail"
9586                         );
9587                 }
9588                 *mtp = statb.st_mtime;
9589         }
9590         mail_var_path_changed = 0;
9591         popstackmark(&smark);
9592 }
9593
9594 static void
9595 changemail(const char *val UNUSED_PARAM)
9596 {
9597         mail_var_path_changed = 1;
9598 }
9599
9600 #endif /* ASH_MAIL */
9601
9602
9603 /* ============ ??? */
9604
9605 /*
9606  * Set the shell parameters.
9607  */
9608 static void
9609 setparam(char **argv)
9610 {
9611         char **newparam;
9612         char **ap;
9613         int nparam;
9614
9615         for (nparam = 0; argv[nparam]; nparam++)
9616                 continue;
9617         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9618         while (*argv) {
9619                 *ap++ = ckstrdup(*argv++);
9620         }
9621         *ap = NULL;
9622         freeparam(&shellparam);
9623         shellparam.malloced = 1;
9624         shellparam.nparam = nparam;
9625         shellparam.p = newparam;
9626 #if ENABLE_ASH_GETOPTS
9627         shellparam.optind = 1;
9628         shellparam.optoff = -1;
9629 #endif
9630 }
9631
9632 /*
9633  * Process shell options.  The global variable argptr contains a pointer
9634  * to the argument list; we advance it past the options.
9635  *
9636  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9637  * For a non-interactive shell, an error condition encountered
9638  * by a special built-in ... shall cause the shell to write a diagnostic message
9639  * to standard error and exit as shown in the following table:
9640  * Error                                           Special Built-In
9641  * ...
9642  * Utility syntax error (option or operand error)  Shall exit
9643  * ...
9644  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9645  * we see that bash does not do that (set "finishes" with error code 1 instead,
9646  * and shell continues), and people rely on this behavior!
9647  * Testcase:
9648  * set -o barfoo 2>/dev/null
9649  * echo $?
9650  *
9651  * Oh well. Let's mimic that.
9652  */
9653 static int
9654 plus_minus_o(char *name, int val)
9655 {
9656         int i;
9657
9658         if (name) {
9659                 for (i = 0; i < NOPTS; i++) {
9660                         if (strcmp(name, optnames(i)) == 0) {
9661                                 optlist[i] = val;
9662                                 return 0;
9663                         }
9664                 }
9665                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9666                 return 1;
9667         }
9668         for (i = 0; i < NOPTS; i++) {
9669                 if (val) {
9670                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9671                 } else {
9672                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9673                 }
9674         }
9675         return 0;
9676 }
9677 static void
9678 setoption(int flag, int val)
9679 {
9680         int i;
9681
9682         for (i = 0; i < NOPTS; i++) {
9683                 if (optletters(i) == flag) {
9684                         optlist[i] = val;
9685                         return;
9686                 }
9687         }
9688         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9689         /* NOTREACHED */
9690 }
9691 static int
9692 options(int cmdline)
9693 {
9694         char *p;
9695         int val;
9696         int c;
9697
9698         if (cmdline)
9699                 minusc = NULL;
9700         while ((p = *argptr) != NULL) {
9701                 c = *p++;
9702                 if (c != '-' && c != '+')
9703                         break;
9704                 argptr++;
9705                 val = 0; /* val = 0 if c == '+' */
9706                 if (c == '-') {
9707                         val = 1;
9708                         if (p[0] == '\0' || LONE_DASH(p)) {
9709                                 if (!cmdline) {
9710                                         /* "-" means turn off -x and -v */
9711                                         if (p[0] == '\0')
9712                                                 xflag = vflag = 0;
9713                                         /* "--" means reset params */
9714                                         else if (*argptr == NULL)
9715                                                 setparam(argptr);
9716                                 }
9717                                 break;    /* "-" or  "--" terminates options */
9718                         }
9719                 }
9720                 /* first char was + or - */
9721                 while ((c = *p++) != '\0') {
9722                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9723                         if (c == 'c' && cmdline) {
9724                                 minusc = p;     /* command is after shell args */
9725                         } else if (c == 'o') {
9726                                 if (plus_minus_o(*argptr, val)) {
9727                                         /* it already printed err message */
9728                                         return 1; /* error */
9729                                 }
9730                                 if (*argptr)
9731                                         argptr++;
9732                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9733                                 isloginsh = 1;
9734                         /* bash does not accept +-login, we also won't */
9735                         } else if (cmdline && val && (c == '-')) { /* long options */
9736                                 if (strcmp(p, "login") == 0)
9737                                         isloginsh = 1;
9738                                 break;
9739                         } else {
9740                                 setoption(c, val);
9741                         }
9742                 }
9743         }
9744         return 0;
9745 }
9746
9747 /*
9748  * The shift builtin command.
9749  */
9750 static int
9751 shiftcmd(int argc UNUSED_PARAM, char **argv)
9752 {
9753         int n;
9754         char **ap1, **ap2;
9755
9756         n = 1;
9757         if (argv[1])
9758                 n = number(argv[1]);
9759         if (n > shellparam.nparam)
9760                 n = 0; /* bash compat, was = shellparam.nparam; */
9761         INT_OFF;
9762         shellparam.nparam -= n;
9763         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9764                 if (shellparam.malloced)
9765                         free(*ap1);
9766         }
9767         ap2 = shellparam.p;
9768         while ((*ap2++ = *ap1++) != NULL)
9769                 continue;
9770 #if ENABLE_ASH_GETOPTS
9771         shellparam.optind = 1;
9772         shellparam.optoff = -1;
9773 #endif
9774         INT_ON;
9775         return 0;
9776 }
9777
9778 /*
9779  * POSIX requires that 'set' (but not export or readonly) output the
9780  * variables in lexicographic order - by the locale's collating order (sigh).
9781  * Maybe we could keep them in an ordered balanced binary tree
9782  * instead of hashed lists.
9783  * For now just roll 'em through qsort for printing...
9784  */
9785 static int
9786 showvars(const char *sep_prefix, int on, int off)
9787 {
9788         const char *sep;
9789         char **ep, **epend;
9790
9791         ep = listvars(on, off, &epend);
9792         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9793
9794         sep = *sep_prefix ? " " : sep_prefix;
9795
9796         for (; ep < epend; ep++) {
9797                 const char *p;
9798                 const char *q;
9799
9800                 p = strchrnul(*ep, '=');
9801                 q = nullstr;
9802                 if (*p)
9803                         q = single_quote(++p);
9804                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9805         }
9806         return 0;
9807 }
9808
9809 /*
9810  * The set command builtin.
9811  */
9812 static int
9813 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9814 {
9815         int retval;
9816
9817         if (!argv[1])
9818                 return showvars(nullstr, 0, VUNSET);
9819         INT_OFF;
9820         retval = 1;
9821         if (!options(0)) { /* if no parse error... */
9822                 retval = 0;
9823                 optschanged();
9824                 if (*argptr != NULL) {
9825                         setparam(argptr);
9826                 }
9827         }
9828         INT_ON;
9829         return retval;
9830 }
9831
9832 #if ENABLE_ASH_RANDOM_SUPPORT
9833 static void
9834 change_random(const char *value)
9835 {
9836         /* Galois LFSR parameter */
9837         /* Taps at 32 31 29 1: */
9838         enum { MASK = 0x8000000b };
9839         /* Another example - taps at 32 31 30 10: */
9840         /* MASK = 0x00400007 */
9841
9842         if (value == NULL) {
9843                 /* "get", generate */
9844                 uint32_t t;
9845
9846                 /* LCG has period of 2^32 and alternating lowest bit */
9847                 random_LCG = 1664525 * random_LCG + 1013904223;
9848                 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9849                 t = (random_galois_LFSR << 1);
9850                 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9851                         t ^= MASK;
9852                 random_galois_LFSR = t;
9853                 /* Both are weak, combining them gives better randomness
9854                  * and ~2^64 period. & 0x7fff is probably bash compat
9855                  * for $RANDOM range. Combining with subtraction is
9856                  * just for fun. + and ^ would work equally well. */
9857                 t = (t - random_LCG) & 0x7fff;
9858                 /* set without recursion */
9859                 setvar(vrandom.text, utoa(t), VNOFUNC);
9860                 vrandom.flags &= ~VNOFUNC;
9861         } else {
9862                 /* set/reset */
9863                 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9864         }
9865 }
9866 #endif
9867
9868 #if ENABLE_ASH_GETOPTS
9869 static int
9870 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9871 {
9872         char *p, *q;
9873         char c = '?';
9874         int done = 0;
9875         int err = 0;
9876         char s[12];
9877         char **optnext;
9878
9879         if (*param_optind < 1)
9880                 return 1;
9881         optnext = optfirst + *param_optind - 1;
9882
9883         if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9884                 p = NULL;
9885         else
9886                 p = optnext[-1] + *optoff;
9887         if (p == NULL || *p == '\0') {
9888                 /* Current word is done, advance */
9889                 p = *optnext;
9890                 if (p == NULL || *p != '-' || *++p == '\0') {
9891  atend:
9892                         p = NULL;
9893                         done = 1;
9894                         goto out;
9895                 }
9896                 optnext++;
9897                 if (LONE_DASH(p))        /* check for "--" */
9898                         goto atend;
9899         }
9900
9901         c = *p++;
9902         for (q = optstr; *q != c;) {
9903                 if (*q == '\0') {
9904                         if (optstr[0] == ':') {
9905                                 s[0] = c;
9906                                 s[1] = '\0';
9907                                 err |= setvarsafe("OPTARG", s, 0);
9908                         } else {
9909                                 fprintf(stderr, "Illegal option -%c\n", c);
9910                                 unsetvar("OPTARG");
9911                         }
9912                         c = '?';
9913                         goto out;
9914                 }
9915                 if (*++q == ':')
9916                         q++;
9917         }
9918
9919         if (*++q == ':') {
9920                 if (*p == '\0' && (p = *optnext) == NULL) {
9921                         if (optstr[0] == ':') {
9922                                 s[0] = c;
9923                                 s[1] = '\0';
9924                                 err |= setvarsafe("OPTARG", s, 0);
9925                                 c = ':';
9926                         } else {
9927                                 fprintf(stderr, "No arg for -%c option\n", c);
9928                                 unsetvar("OPTARG");
9929                                 c = '?';
9930                         }
9931                         goto out;
9932                 }
9933
9934                 if (p == *optnext)
9935                         optnext++;
9936                 err |= setvarsafe("OPTARG", p, 0);
9937                 p = NULL;
9938         } else
9939                 err |= setvarsafe("OPTARG", nullstr, 0);
9940  out:
9941         *optoff = p ? p - *(optnext - 1) : -1;
9942         *param_optind = optnext - optfirst + 1;
9943         fmtstr(s, sizeof(s), "%d", *param_optind);
9944         err |= setvarsafe("OPTIND", s, VNOFUNC);
9945         s[0] = c;
9946         s[1] = '\0';
9947         err |= setvarsafe(optvar, s, 0);
9948         if (err) {
9949                 *param_optind = 1;
9950                 *optoff = -1;
9951                 flush_stdout_stderr();
9952                 raise_exception(EXERROR);
9953         }
9954         return done;
9955 }
9956
9957 /*
9958  * The getopts builtin.  Shellparam.optnext points to the next argument
9959  * to be processed.  Shellparam.optptr points to the next character to
9960  * be processed in the current argument.  If shellparam.optnext is NULL,
9961  * then it's the first time getopts has been called.
9962  */
9963 static int
9964 getoptscmd(int argc, char **argv)
9965 {
9966         char **optbase;
9967
9968         if (argc < 3)
9969                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9970         if (argc == 3) {
9971                 optbase = shellparam.p;
9972                 if (shellparam.optind > shellparam.nparam + 1) {
9973                         shellparam.optind = 1;
9974                         shellparam.optoff = -1;
9975                 }
9976         } else {
9977                 optbase = &argv[3];
9978                 if (shellparam.optind > argc - 2) {
9979                         shellparam.optind = 1;
9980                         shellparam.optoff = -1;
9981                 }
9982         }
9983
9984         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9985                         &shellparam.optoff);
9986 }
9987 #endif /* ASH_GETOPTS */
9988
9989
9990 /* ============ Shell parser */
9991
9992 struct heredoc {
9993         struct heredoc *next;   /* next here document in list */
9994         union node *here;       /* redirection node */
9995         char *eofmark;          /* string indicating end of input */
9996         smallint striptabs;     /* if set, strip leading tabs */
9997 };
9998
9999 static smallint tokpushback;           /* last token pushed back */
10000 static smallint parsebackquote;        /* nonzero if we are inside backquotes */
10001 static smallint quoteflag;             /* set if (part of) last token was quoted */
10002 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10003 static struct heredoc *heredoclist;    /* list of here documents to read */
10004 static char *wordtext;                 /* text of last word returned by readtoken */
10005 static struct nodelist *backquotelist;
10006 static union node *redirnode;
10007 static struct heredoc *heredoc;
10008 /*
10009  * NEOF is returned by parsecmd when it encounters an end of file.  It
10010  * must be distinct from NULL, so we use the address of a variable that
10011  * happens to be handy.
10012  */
10013 #define NEOF ((union node *)&tokpushback)
10014
10015 static void raise_error_syntax(const char *) NORETURN;
10016 static void
10017 raise_error_syntax(const char *msg)
10018 {
10019         ash_msg_and_raise_error("syntax error: %s", msg);
10020         /* NOTREACHED */
10021 }
10022
10023 /*
10024  * Called when an unexpected token is read during the parse.  The argument
10025  * is the token that is expected, or -1 if more than one type of token can
10026  * occur at this point.
10027  */
10028 static void raise_error_unexpected_syntax(int) NORETURN;
10029 static void
10030 raise_error_unexpected_syntax(int token)
10031 {
10032         char msg[64];
10033         int l;
10034
10035         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10036         if (token >= 0)
10037                 sprintf(msg + l, " (expecting %s)", tokname(token));
10038         raise_error_syntax(msg);
10039         /* NOTREACHED */
10040 }
10041
10042 #define EOFMARKLEN 79
10043
10044 /* parsing is heavily cross-recursive, need these forward decls */
10045 static union node *andor(void);
10046 static union node *pipeline(void);
10047 static union node *parse_command(void);
10048 static void parseheredoc(void);
10049 static char peektoken(void);
10050 static int readtoken(void);
10051
10052 static union node *
10053 list(int nlflag)
10054 {
10055         union node *n1, *n2, *n3;
10056         int tok;
10057
10058         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10059         if (nlflag == 2 && peektoken())
10060                 return NULL;
10061         n1 = NULL;
10062         for (;;) {
10063                 n2 = andor();
10064                 tok = readtoken();
10065                 if (tok == TBACKGND) {
10066                         if (n2->type == NPIPE) {
10067                                 n2->npipe.pipe_backgnd = 1;
10068                         } else {
10069                                 if (n2->type != NREDIR) {
10070                                         n3 = stzalloc(sizeof(struct nredir));
10071                                         n3->nredir.n = n2;
10072                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10073                                         n2 = n3;
10074                                 }
10075                                 n2->type = NBACKGND;
10076                         }
10077                 }
10078                 if (n1 == NULL) {
10079                         n1 = n2;
10080                 } else {
10081                         n3 = stzalloc(sizeof(struct nbinary));
10082                         n3->type = NSEMI;
10083                         n3->nbinary.ch1 = n1;
10084                         n3->nbinary.ch2 = n2;
10085                         n1 = n3;
10086                 }
10087                 switch (tok) {
10088                 case TBACKGND:
10089                 case TSEMI:
10090                         tok = readtoken();
10091                         /* fall through */
10092                 case TNL:
10093                         if (tok == TNL) {
10094                                 parseheredoc();
10095                                 if (nlflag == 1)
10096                                         return n1;
10097                         } else {
10098                                 tokpushback = 1;
10099                         }
10100                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10101                         if (peektoken())
10102                                 return n1;
10103                         break;
10104                 case TEOF:
10105                         if (heredoclist)
10106                                 parseheredoc();
10107                         else
10108                                 pungetc();              /* push back EOF on input */
10109                         return n1;
10110                 default:
10111                         if (nlflag == 1)
10112                                 raise_error_unexpected_syntax(-1);
10113                         tokpushback = 1;
10114                         return n1;
10115                 }
10116         }
10117 }
10118
10119 static union node *
10120 andor(void)
10121 {
10122         union node *n1, *n2, *n3;
10123         int t;
10124
10125         n1 = pipeline();
10126         for (;;) {
10127                 t = readtoken();
10128                 if (t == TAND) {
10129                         t = NAND;
10130                 } else if (t == TOR) {
10131                         t = NOR;
10132                 } else {
10133                         tokpushback = 1;
10134                         return n1;
10135                 }
10136                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10137                 n2 = pipeline();
10138                 n3 = stzalloc(sizeof(struct nbinary));
10139                 n3->type = t;
10140                 n3->nbinary.ch1 = n1;
10141                 n3->nbinary.ch2 = n2;
10142                 n1 = n3;
10143         }
10144 }
10145
10146 static union node *
10147 pipeline(void)
10148 {
10149         union node *n1, *n2, *pipenode;
10150         struct nodelist *lp, *prev;
10151         int negate;
10152
10153         negate = 0;
10154         TRACE(("pipeline: entered\n"));
10155         if (readtoken() == TNOT) {
10156                 negate = !negate;
10157                 checkkwd = CHKKWD | CHKALIAS;
10158         } else
10159                 tokpushback = 1;
10160         n1 = parse_command();
10161         if (readtoken() == TPIPE) {
10162                 pipenode = stzalloc(sizeof(struct npipe));
10163                 pipenode->type = NPIPE;
10164                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10165                 lp = stzalloc(sizeof(struct nodelist));
10166                 pipenode->npipe.cmdlist = lp;
10167                 lp->n = n1;
10168                 do {
10169                         prev = lp;
10170                         lp = stzalloc(sizeof(struct nodelist));
10171                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10172                         lp->n = parse_command();
10173                         prev->next = lp;
10174                 } while (readtoken() == TPIPE);
10175                 lp->next = NULL;
10176                 n1 = pipenode;
10177         }
10178         tokpushback = 1;
10179         if (negate) {
10180                 n2 = stzalloc(sizeof(struct nnot));
10181                 n2->type = NNOT;
10182                 n2->nnot.com = n1;
10183                 return n2;
10184         }
10185         return n1;
10186 }
10187
10188 static union node *
10189 makename(void)
10190 {
10191         union node *n;
10192
10193         n = stzalloc(sizeof(struct narg));
10194         n->type = NARG;
10195         /*n->narg.next = NULL; - stzalloc did it */
10196         n->narg.text = wordtext;
10197         n->narg.backquote = backquotelist;
10198         return n;
10199 }
10200
10201 static void
10202 fixredir(union node *n, const char *text, int err)
10203 {
10204         int fd;
10205
10206         TRACE(("Fix redir %s %d\n", text, err));
10207         if (!err)
10208                 n->ndup.vname = NULL;
10209
10210         fd = bb_strtou(text, NULL, 10);
10211         if (!errno && fd >= 0)
10212                 n->ndup.dupfd = fd;
10213         else if (LONE_DASH(text))
10214                 n->ndup.dupfd = -1;
10215         else {
10216                 if (err)
10217                         raise_error_syntax("bad fd number");
10218                 n->ndup.vname = makename();
10219         }
10220 }
10221
10222 /*
10223  * Returns true if the text contains nothing to expand (no dollar signs
10224  * or backquotes).
10225  */
10226 static int
10227 noexpand(char *text)
10228 {
10229         char *p;
10230         char c;
10231
10232         p = text;
10233         while ((c = *p++) != '\0') {
10234                 if (c == CTLQUOTEMARK)
10235                         continue;
10236                 if (c == CTLESC)
10237                         p++;
10238                 else if (SIT(c, BASESYNTAX) == CCTL)
10239                         return 0;
10240         }
10241         return 1;
10242 }
10243
10244 static void
10245 parsefname(void)
10246 {
10247         union node *n = redirnode;
10248
10249         if (readtoken() != TWORD)
10250                 raise_error_unexpected_syntax(-1);
10251         if (n->type == NHERE) {
10252                 struct heredoc *here = heredoc;
10253                 struct heredoc *p;
10254                 int i;
10255
10256                 if (quoteflag == 0)
10257                         n->type = NXHERE;
10258                 TRACE(("Here document %d\n", n->type));
10259                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10260                         raise_error_syntax("illegal eof marker for << redirection");
10261                 rmescapes(wordtext);
10262                 here->eofmark = wordtext;
10263                 here->next = NULL;
10264                 if (heredoclist == NULL)
10265                         heredoclist = here;
10266                 else {
10267                         for (p = heredoclist; p->next; p = p->next)
10268                                 continue;
10269                         p->next = here;
10270                 }
10271         } else if (n->type == NTOFD || n->type == NFROMFD) {
10272                 fixredir(n, wordtext, 0);
10273         } else {
10274                 n->nfile.fname = makename();
10275         }
10276 }
10277
10278 static union node *
10279 simplecmd(void)
10280 {
10281         union node *args, **app;
10282         union node *n = NULL;
10283         union node *vars, **vpp;
10284         union node **rpp, *redir;
10285         int savecheckkwd;
10286 #if ENABLE_ASH_BASH_COMPAT
10287         smallint double_brackets_flag = 0;
10288 #endif
10289
10290         args = NULL;
10291         app = &args;
10292         vars = NULL;
10293         vpp = &vars;
10294         redir = NULL;
10295         rpp = &redir;
10296
10297         savecheckkwd = CHKALIAS;
10298         for (;;) {
10299                 int t;
10300                 checkkwd = savecheckkwd;
10301                 t = readtoken();
10302                 switch (t) {
10303 #if ENABLE_ASH_BASH_COMPAT
10304                 case TAND: /* "&&" */
10305                 case TOR: /* "||" */
10306                         if (!double_brackets_flag) {
10307                                 tokpushback = 1;
10308                                 goto out;
10309                         }
10310                         wordtext = (char *) (t == TAND ? "-a" : "-o");
10311 #endif
10312                 case TWORD:
10313                         n = stzalloc(sizeof(struct narg));
10314                         n->type = NARG;
10315                         /*n->narg.next = NULL; - stzalloc did it */
10316                         n->narg.text = wordtext;
10317 #if ENABLE_ASH_BASH_COMPAT
10318                         if (strcmp("[[", wordtext) == 0)
10319                                 double_brackets_flag = 1;
10320                         else if (strcmp("]]", wordtext) == 0)
10321                                 double_brackets_flag = 0;
10322 #endif
10323                         n->narg.backquote = backquotelist;
10324                         if (savecheckkwd && isassignment(wordtext)) {
10325                                 *vpp = n;
10326                                 vpp = &n->narg.next;
10327                         } else {
10328                                 *app = n;
10329                                 app = &n->narg.next;
10330                                 savecheckkwd = 0;
10331                         }
10332                         break;
10333                 case TREDIR:
10334                         *rpp = n = redirnode;
10335                         rpp = &n->nfile.next;
10336                         parsefname();   /* read name of redirection file */
10337                         break;
10338                 case TLP:
10339                         if (args && app == &args->narg.next
10340                          && !vars && !redir
10341                         ) {
10342                                 struct builtincmd *bcmd;
10343                                 const char *name;
10344
10345                                 /* We have a function */
10346                                 if (readtoken() != TRP)
10347                                         raise_error_unexpected_syntax(TRP);
10348                                 name = n->narg.text;
10349                                 if (!goodname(name)
10350                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10351                                 ) {
10352                                         raise_error_syntax("bad function name");
10353                                 }
10354                                 n->type = NDEFUN;
10355                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10356                                 n->narg.next = parse_command();
10357                                 return n;
10358                         }
10359                         /* fall through */
10360                 default:
10361                         tokpushback = 1;
10362                         goto out;
10363                 }
10364         }
10365  out:
10366         *app = NULL;
10367         *vpp = NULL;
10368         *rpp = NULL;
10369         n = stzalloc(sizeof(struct ncmd));
10370         n->type = NCMD;
10371         n->ncmd.args = args;
10372         n->ncmd.assign = vars;
10373         n->ncmd.redirect = redir;
10374         return n;
10375 }
10376
10377 static union node *
10378 parse_command(void)
10379 {
10380         union node *n1, *n2;
10381         union node *ap, **app;
10382         union node *cp, **cpp;
10383         union node *redir, **rpp;
10384         union node **rpp2;
10385         int t;
10386
10387         redir = NULL;
10388         rpp2 = &redir;
10389
10390         switch (readtoken()) {
10391         default:
10392                 raise_error_unexpected_syntax(-1);
10393                 /* NOTREACHED */
10394         case TIF:
10395                 n1 = stzalloc(sizeof(struct nif));
10396                 n1->type = NIF;
10397                 n1->nif.test = list(0);
10398                 if (readtoken() != TTHEN)
10399                         raise_error_unexpected_syntax(TTHEN);
10400                 n1->nif.ifpart = list(0);
10401                 n2 = n1;
10402                 while (readtoken() == TELIF) {
10403                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
10404                         n2 = n2->nif.elsepart;
10405                         n2->type = NIF;
10406                         n2->nif.test = list(0);
10407                         if (readtoken() != TTHEN)
10408                                 raise_error_unexpected_syntax(TTHEN);
10409                         n2->nif.ifpart = list(0);
10410                 }
10411                 if (lasttoken == TELSE)
10412                         n2->nif.elsepart = list(0);
10413                 else {
10414                         n2->nif.elsepart = NULL;
10415                         tokpushback = 1;
10416                 }
10417                 t = TFI;
10418                 break;
10419         case TWHILE:
10420         case TUNTIL: {
10421                 int got;
10422                 n1 = stzalloc(sizeof(struct nbinary));
10423                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10424                 n1->nbinary.ch1 = list(0);
10425                 got = readtoken();
10426                 if (got != TDO) {
10427                         TRACE(("expecting DO got %s %s\n", tokname(got),
10428                                         got == TWORD ? wordtext : ""));
10429                         raise_error_unexpected_syntax(TDO);
10430                 }
10431                 n1->nbinary.ch2 = list(0);
10432                 t = TDONE;
10433                 break;
10434         }
10435         case TFOR:
10436                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10437                         raise_error_syntax("bad for loop variable");
10438                 n1 = stzalloc(sizeof(struct nfor));
10439                 n1->type = NFOR;
10440                 n1->nfor.var = wordtext;
10441                 checkkwd = CHKKWD | CHKALIAS;
10442                 if (readtoken() == TIN) {
10443                         app = &ap;
10444                         while (readtoken() == TWORD) {
10445                                 n2 = stzalloc(sizeof(struct narg));
10446                                 n2->type = NARG;
10447                                 /*n2->narg.next = NULL; - stzalloc did it */
10448                                 n2->narg.text = wordtext;
10449                                 n2->narg.backquote = backquotelist;
10450                                 *app = n2;
10451                                 app = &n2->narg.next;
10452                         }
10453                         *app = NULL;
10454                         n1->nfor.args = ap;
10455                         if (lasttoken != TNL && lasttoken != TSEMI)
10456                                 raise_error_unexpected_syntax(-1);
10457                 } else {
10458                         n2 = stzalloc(sizeof(struct narg));
10459                         n2->type = NARG;
10460                         /*n2->narg.next = NULL; - stzalloc did it */
10461                         n2->narg.text = (char *)dolatstr;
10462                         /*n2->narg.backquote = NULL;*/
10463                         n1->nfor.args = n2;
10464                         /*
10465                          * Newline or semicolon here is optional (but note
10466                          * that the original Bourne shell only allowed NL).
10467                          */
10468                         if (lasttoken != TNL && lasttoken != TSEMI)
10469                                 tokpushback = 1;
10470                 }
10471                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10472                 if (readtoken() != TDO)
10473                         raise_error_unexpected_syntax(TDO);
10474                 n1->nfor.body = list(0);
10475                 t = TDONE;
10476                 break;
10477         case TCASE:
10478                 n1 = stzalloc(sizeof(struct ncase));
10479                 n1->type = NCASE;
10480                 if (readtoken() != TWORD)
10481                         raise_error_unexpected_syntax(TWORD);
10482                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10483                 n2->type = NARG;
10484                 /*n2->narg.next = NULL; - stzalloc did it */
10485                 n2->narg.text = wordtext;
10486                 n2->narg.backquote = backquotelist;
10487                 do {
10488                         checkkwd = CHKKWD | CHKALIAS;
10489                 } while (readtoken() == TNL);
10490                 if (lasttoken != TIN)
10491                         raise_error_unexpected_syntax(TIN);
10492                 cpp = &n1->ncase.cases;
10493  next_case:
10494                 checkkwd = CHKNL | CHKKWD;
10495                 t = readtoken();
10496                 while (t != TESAC) {
10497                         if (lasttoken == TLP)
10498                                 readtoken();
10499                         *cpp = cp = stzalloc(sizeof(struct nclist));
10500                         cp->type = NCLIST;
10501                         app = &cp->nclist.pattern;
10502                         for (;;) {
10503                                 *app = ap = stzalloc(sizeof(struct narg));
10504                                 ap->type = NARG;
10505                                 /*ap->narg.next = NULL; - stzalloc did it */
10506                                 ap->narg.text = wordtext;
10507                                 ap->narg.backquote = backquotelist;
10508                                 if (readtoken() != TPIPE)
10509                                         break;
10510                                 app = &ap->narg.next;
10511                                 readtoken();
10512                         }
10513                         //ap->narg.next = NULL;
10514                         if (lasttoken != TRP)
10515                                 raise_error_unexpected_syntax(TRP);
10516                         cp->nclist.body = list(2);
10517
10518                         cpp = &cp->nclist.next;
10519
10520                         checkkwd = CHKNL | CHKKWD;
10521                         t = readtoken();
10522                         if (t != TESAC) {
10523                                 if (t != TENDCASE)
10524                                         raise_error_unexpected_syntax(TENDCASE);
10525                                 goto next_case;
10526                         }
10527                 }
10528                 *cpp = NULL;
10529                 goto redir;
10530         case TLP:
10531                 n1 = stzalloc(sizeof(struct nredir));
10532                 n1->type = NSUBSHELL;
10533                 n1->nredir.n = list(0);
10534                 /*n1->nredir.redirect = NULL; - stzalloc did it */
10535                 t = TRP;
10536                 break;
10537         case TBEGIN:
10538                 n1 = list(0);
10539                 t = TEND;
10540                 break;
10541         case TWORD:
10542         case TREDIR:
10543                 tokpushback = 1;
10544                 return simplecmd();
10545         }
10546
10547         if (readtoken() != t)
10548                 raise_error_unexpected_syntax(t);
10549
10550  redir:
10551         /* Now check for redirection which may follow command */
10552         checkkwd = CHKKWD | CHKALIAS;
10553         rpp = rpp2;
10554         while (readtoken() == TREDIR) {
10555                 *rpp = n2 = redirnode;
10556                 rpp = &n2->nfile.next;
10557                 parsefname();
10558         }
10559         tokpushback = 1;
10560         *rpp = NULL;
10561         if (redir) {
10562                 if (n1->type != NSUBSHELL) {
10563                         n2 = stzalloc(sizeof(struct nredir));
10564                         n2->type = NREDIR;
10565                         n2->nredir.n = n1;
10566                         n1 = n2;
10567                 }
10568                 n1->nredir.redirect = redir;
10569         }
10570         return n1;
10571 }
10572
10573 #if ENABLE_ASH_BASH_COMPAT
10574 static int decode_dollar_squote(void)
10575 {
10576         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10577         int c, cnt;
10578         char *p;
10579         char buf[4];
10580
10581         c = pgetc();
10582         p = strchr(C_escapes, c);
10583         if (p) {
10584                 buf[0] = c;
10585                 p = buf;
10586                 cnt = 3;
10587                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10588                         do {
10589                                 c = pgetc();
10590                                 *++p = c;
10591                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
10592                         pungetc();
10593                 } else if (c == 'x') { /* \xHH */
10594                         do {
10595                                 c = pgetc();
10596                                 *++p = c;
10597                         } while (isxdigit(c) && --cnt);
10598                         pungetc();
10599                         if (cnt == 3) { /* \x but next char is "bad" */
10600                                 c = 'x';
10601                                 goto unrecognized;
10602                         }
10603                 } else { /* simple seq like \\ or \t */
10604                         p++;
10605                 }
10606                 *p = '\0';
10607                 p = buf;
10608                 c = bb_process_escape_sequence((void*)&p);
10609         } else { /* unrecognized "\z": print both chars unless ' or " */
10610                 if (c != '\'' && c != '"') {
10611  unrecognized:
10612                         c |= 0x100; /* "please encode \, then me" */
10613                 }
10614         }
10615         return c;
10616 }
10617 #endif
10618
10619 /*
10620  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10621  * is not NULL, read a here document.  In the latter case, eofmark is the
10622  * word which marks the end of the document and striptabs is true if
10623  * leading tabs should be stripped from the document.  The argument firstc
10624  * is the first character of the input token or document.
10625  *
10626  * Because C does not have internal subroutines, I have simulated them
10627  * using goto's to implement the subroutine linkage.  The following macros
10628  * will run code that appears at the end of readtoken1.
10629  */
10630 #define CHECKEND()      {goto checkend; checkend_return:;}
10631 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10632 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10633 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10634 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10635 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10636 static int
10637 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10638 {
10639         /* NB: syntax parameter fits into smallint */
10640         int c = firstc;
10641         char *out;
10642         int len;
10643         char line[EOFMARKLEN + 1];
10644         struct nodelist *bqlist;
10645         smallint quotef;
10646         smallint dblquote;
10647         smallint oldstyle;
10648         smallint prevsyntax; /* syntax before arithmetic */
10649 #if ENABLE_ASH_EXPAND_PRMT
10650         smallint pssyntax;   /* we are expanding a prompt string */
10651 #endif
10652         int varnest;         /* levels of variables expansion */
10653         int arinest;         /* levels of arithmetic expansion */
10654         int parenlevel;      /* levels of parens in arithmetic */
10655         int dqvarnest;       /* levels of variables expansion within double quotes */
10656
10657         USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10658
10659 #if __GNUC__
10660         /* Avoid longjmp clobbering */
10661         (void) &out;
10662         (void) &quotef;
10663         (void) &dblquote;
10664         (void) &varnest;
10665         (void) &arinest;
10666         (void) &parenlevel;
10667         (void) &dqvarnest;
10668         (void) &oldstyle;
10669         (void) &prevsyntax;
10670         (void) &syntax;
10671 #endif
10672         startlinno = g_parsefile->linno;
10673         bqlist = NULL;
10674         quotef = 0;
10675         oldstyle = 0;
10676         prevsyntax = 0;
10677 #if ENABLE_ASH_EXPAND_PRMT
10678         pssyntax = (syntax == PSSYNTAX);
10679         if (pssyntax)
10680                 syntax = DQSYNTAX;
10681 #endif
10682         dblquote = (syntax == DQSYNTAX);
10683         varnest = 0;
10684         arinest = 0;
10685         parenlevel = 0;
10686         dqvarnest = 0;
10687
10688         STARTSTACKSTR(out);
10689  loop:
10690         /* For each line, until end of word */
10691         {
10692                 CHECKEND();     /* set c to PEOF if at end of here document */
10693                 for (;;) {      /* until end of line or end of word */
10694                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10695                         switch (SIT(c, syntax)) {
10696                         case CNL:       /* '\n' */
10697                                 if (syntax == BASESYNTAX)
10698                                         goto endword;   /* exit outer loop */
10699                                 USTPUTC(c, out);
10700                                 g_parsefile->linno++;
10701                                 if (doprompt)
10702                                         setprompt(2);
10703                                 c = pgetc();
10704                                 goto loop;              /* continue outer loop */
10705                         case CWORD:
10706                                 USTPUTC(c, out);
10707                                 break;
10708                         case CCTL:
10709                                 if (eofmark == NULL || dblquote)
10710                                         USTPUTC(CTLESC, out);
10711 #if ENABLE_ASH_BASH_COMPAT
10712                                 if (c == '\\' && bash_dollar_squote) {
10713                                         c = decode_dollar_squote();
10714                                         if (c & 0x100) {
10715                                                 USTPUTC('\\', out);
10716                                                 c = (unsigned char)c;
10717                                         }
10718                                 }
10719 #endif
10720                                 USTPUTC(c, out);
10721                                 break;
10722                         case CBACK:     /* backslash */
10723                                 c = pgetc2();
10724                                 if (c == PEOF) {
10725                                         USTPUTC(CTLESC, out);
10726                                         USTPUTC('\\', out);
10727                                         pungetc();
10728                                 } else if (c == '\n') {
10729                                         if (doprompt)
10730                                                 setprompt(2);
10731                                 } else {
10732 #if ENABLE_ASH_EXPAND_PRMT
10733                                         if (c == '$' && pssyntax) {
10734                                                 USTPUTC(CTLESC, out);
10735                                                 USTPUTC('\\', out);
10736                                         }
10737 #endif
10738                                         if (dblquote && c != '\\'
10739                                          && c != '`' && c != '$'
10740                                          && (c != '"' || eofmark != NULL)
10741                                         ) {
10742                                                 USTPUTC(CTLESC, out);
10743                                                 USTPUTC('\\', out);
10744                                         }
10745                                         if (SIT(c, SQSYNTAX) == CCTL)
10746                                                 USTPUTC(CTLESC, out);
10747                                         USTPUTC(c, out);
10748                                         quotef = 1;
10749                                 }
10750                                 break;
10751                         case CSQUOTE:
10752                                 syntax = SQSYNTAX;
10753  quotemark:
10754                                 if (eofmark == NULL) {
10755                                         USTPUTC(CTLQUOTEMARK, out);
10756                                 }
10757                                 break;
10758                         case CDQUOTE:
10759                                 syntax = DQSYNTAX;
10760                                 dblquote = 1;
10761                                 goto quotemark;
10762                         case CENDQUOTE:
10763                                 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10764                                 if (eofmark != NULL && arinest == 0
10765                                  && varnest == 0
10766                                 ) {
10767                                         USTPUTC(c, out);
10768                                 } else {
10769                                         if (dqvarnest == 0) {
10770                                                 syntax = BASESYNTAX;
10771                                                 dblquote = 0;
10772                                         }
10773                                         quotef = 1;
10774                                         goto quotemark;
10775                                 }
10776                                 break;
10777                         case CVAR:      /* '$' */
10778                                 PARSESUB();             /* parse substitution */
10779                                 break;
10780                         case CENDVAR:   /* '}' */
10781                                 if (varnest > 0) {
10782                                         varnest--;
10783                                         if (dqvarnest > 0) {
10784                                                 dqvarnest--;
10785                                         }
10786                                         USTPUTC(CTLENDVAR, out);
10787                                 } else {
10788                                         USTPUTC(c, out);
10789                                 }
10790                                 break;
10791 #if ENABLE_ASH_MATH_SUPPORT
10792                         case CLP:       /* '(' in arithmetic */
10793                                 parenlevel++;
10794                                 USTPUTC(c, out);
10795                                 break;
10796                         case CRP:       /* ')' in arithmetic */
10797                                 if (parenlevel > 0) {
10798                                         USTPUTC(c, out);
10799                                         --parenlevel;
10800                                 } else {
10801                                         if (pgetc() == ')') {
10802                                                 if (--arinest == 0) {
10803                                                         USTPUTC(CTLENDARI, out);
10804                                                         syntax = prevsyntax;
10805                                                         dblquote = (syntax == DQSYNTAX);
10806                                                 } else
10807                                                         USTPUTC(')', out);
10808                                         } else {
10809                                                 /*
10810                                                  * unbalanced parens
10811                                                  *  (don't 2nd guess - no error)
10812                                                  */
10813                                                 pungetc();
10814                                                 USTPUTC(')', out);
10815                                         }
10816                                 }
10817                                 break;
10818 #endif
10819                         case CBQUOTE:   /* '`' */
10820                                 PARSEBACKQOLD();
10821                                 break;
10822                         case CENDFILE:
10823                                 goto endword;           /* exit outer loop */
10824                         case CIGN:
10825                                 break;
10826                         default:
10827                                 if (varnest == 0) {
10828 #if ENABLE_ASH_BASH_COMPAT
10829                                         if (c == '&') {
10830                                                 if (pgetc() == '>')
10831                                                         c = 0x100 + '>'; /* flag &> */
10832                                                 pungetc();
10833                                         }
10834 #endif
10835                                         goto endword;   /* exit outer loop */
10836                                 }
10837 #if ENABLE_ASH_ALIAS
10838                                 if (c != PEOA)
10839 #endif
10840                                         USTPUTC(c, out);
10841
10842                         }
10843                         c = pgetc_fast();
10844                 } /* for (;;) */
10845         }
10846  endword:
10847 #if ENABLE_ASH_MATH_SUPPORT
10848         if (syntax == ARISYNTAX)
10849                 raise_error_syntax("missing '))'");
10850 #endif
10851         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10852                 raise_error_syntax("unterminated quoted string");
10853         if (varnest != 0) {
10854                 startlinno = g_parsefile->linno;
10855                 /* { */
10856                 raise_error_syntax("missing '}'");
10857         }
10858         USTPUTC('\0', out);
10859         len = out - (char *)stackblock();
10860         out = stackblock();
10861         if (eofmark == NULL) {
10862                 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
10863                  && quotef == 0
10864                 ) {
10865                         if (isdigit_str9(out)) {
10866                                 PARSEREDIR(); /* passed as params: out, c */
10867                                 lasttoken = TREDIR;
10868                                 return lasttoken;
10869                         }
10870                         /* else: non-number X seen, interpret it
10871                          * as "NNNX>file" = "NNNX >file" */
10872                 }
10873                 pungetc();
10874         }
10875         quoteflag = quotef;
10876         backquotelist = bqlist;
10877         grabstackblock(len);
10878         wordtext = out;
10879         lasttoken = TWORD;
10880         return lasttoken;
10881 /* end of readtoken routine */
10882
10883 /*
10884  * Check to see whether we are at the end of the here document.  When this
10885  * is called, c is set to the first character of the next input line.  If
10886  * we are at the end of the here document, this routine sets the c to PEOF.
10887  */
10888 checkend: {
10889         if (eofmark) {
10890 #if ENABLE_ASH_ALIAS
10891                 if (c == PEOA) {
10892                         c = pgetc2();
10893                 }
10894 #endif
10895                 if (striptabs) {
10896                         while (c == '\t') {
10897                                 c = pgetc2();
10898                         }
10899                 }
10900                 if (c == *eofmark) {
10901                         if (pfgets(line, sizeof(line)) != NULL) {
10902                                 char *p, *q;
10903
10904                                 p = line;
10905                                 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10906                                         continue;
10907                                 if (*p == '\n' && *q == '\0') {
10908                                         c = PEOF;
10909                                         g_parsefile->linno++;
10910                                         needprompt = doprompt;
10911                                 } else {
10912                                         pushstring(line, NULL);
10913                                 }
10914                         }
10915                 }
10916         }
10917         goto checkend_return;
10918 }
10919
10920 /*
10921  * Parse a redirection operator.  The variable "out" points to a string
10922  * specifying the fd to be redirected.  The variable "c" contains the
10923  * first character of the redirection operator.
10924  */
10925 parseredir: {
10926         /* out is already checked to be a valid number or "" */
10927         int fd = (*out == '\0' ? -1 : atoi(out));
10928         union node *np;
10929
10930         np = stzalloc(sizeof(struct nfile));
10931         if (c == '>') {
10932                 np->nfile.fd = 1;
10933                 c = pgetc();
10934                 if (c == '>')
10935                         np->type = NAPPEND;
10936                 else if (c == '|')
10937                         np->type = NCLOBBER;
10938                 else if (c == '&')
10939                         np->type = NTOFD;
10940                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
10941                 else {
10942                         np->type = NTO;
10943                         pungetc();
10944                 }
10945         }
10946 #if ENABLE_ASH_BASH_COMPAT
10947         else if (c == 0x100 + '>') { /* this flags &> redirection */
10948                 np->nfile.fd = 1;
10949                 pgetc(); /* this is '>', no need to check */
10950                 np->type = NTO2;
10951         }
10952 #endif
10953         else { /* c == '<' */
10954                 /*np->nfile.fd = 0; - stzalloc did it */
10955                 c = pgetc();
10956                 switch (c) {
10957                 case '<':
10958                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10959                                 np = stzalloc(sizeof(struct nhere));
10960                                 /*np->nfile.fd = 0; - stzalloc did it */
10961                         }
10962                         np->type = NHERE;
10963                         heredoc = stzalloc(sizeof(struct heredoc));
10964                         heredoc->here = np;
10965                         c = pgetc();
10966                         if (c == '-') {
10967                                 heredoc->striptabs = 1;
10968                         } else {
10969                                 /*heredoc->striptabs = 0; - stzalloc did it */
10970                                 pungetc();
10971                         }
10972                         break;
10973
10974                 case '&':
10975                         np->type = NFROMFD;
10976                         break;
10977
10978                 case '>':
10979                         np->type = NFROMTO;
10980                         break;
10981
10982                 default:
10983                         np->type = NFROM;
10984                         pungetc();
10985                         break;
10986                 }
10987         }
10988         if (fd >= 0)
10989                 np->nfile.fd = fd;
10990         redirnode = np;
10991         goto parseredir_return;
10992 }
10993
10994 /*
10995  * Parse a substitution.  At this point, we have read the dollar sign
10996  * and nothing else.
10997  */
10998
10999 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11000  * (assuming ascii char codes, as the original implementation did) */
11001 #define is_special(c) \
11002         (((unsigned)(c) - 33 < 32) \
11003                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11004 parsesub: {
11005         int subtype;
11006         int typeloc;
11007         int flags;
11008         char *p;
11009         static const char types[] ALIGN1 = "}-+?=";
11010
11011         c = pgetc();
11012         if (c <= PEOA_OR_PEOF
11013          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11014         ) {
11015 #if ENABLE_ASH_BASH_COMPAT
11016                 if (c == '\'')
11017                         bash_dollar_squote = 1;
11018                 else
11019 #endif
11020                         USTPUTC('$', out);
11021                 pungetc();
11022         } else if (c == '(') {  /* $(command) or $((arith)) */
11023                 if (pgetc() == '(') {
11024 #if ENABLE_ASH_MATH_SUPPORT
11025                         PARSEARITH();
11026 #else
11027                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11028 #endif
11029                 } else {
11030                         pungetc();
11031                         PARSEBACKQNEW();
11032                 }
11033         } else {
11034                 USTPUTC(CTLVAR, out);
11035                 typeloc = out - (char *)stackblock();
11036                 USTPUTC(VSNORMAL, out);
11037                 subtype = VSNORMAL;
11038                 if (c == '{') {
11039                         c = pgetc();
11040                         if (c == '#') {
11041                                 c = pgetc();
11042                                 if (c == '}')
11043                                         c = '#';
11044                                 else
11045                                         subtype = VSLENGTH;
11046                         } else
11047                                 subtype = 0;
11048                 }
11049                 if (c > PEOA_OR_PEOF && is_name(c)) {
11050                         do {
11051                                 STPUTC(c, out);
11052                                 c = pgetc();
11053                         } while (c > PEOA_OR_PEOF && is_in_name(c));
11054                 } else if (isdigit(c)) {
11055                         do {
11056                                 STPUTC(c, out);
11057                                 c = pgetc();
11058                         } while (isdigit(c));
11059                 } else if (is_special(c)) {
11060                         USTPUTC(c, out);
11061                         c = pgetc();
11062                 } else {
11063  badsub:
11064                         raise_error_syntax("bad substitution");
11065                 }
11066
11067                 STPUTC('=', out);
11068                 flags = 0;
11069                 if (subtype == 0) {
11070                         switch (c) {
11071                         case ':':
11072                                 c = pgetc();
11073 #if ENABLE_ASH_BASH_COMPAT
11074                                 if (c == ':' || c == '$' || isdigit(c)) {
11075                                         pungetc();
11076                                         subtype = VSSUBSTR;
11077                                         break;
11078                                 }
11079 #endif
11080                                 flags = VSNUL;
11081                                 /*FALLTHROUGH*/
11082                         default:
11083                                 p = strchr(types, c);
11084                                 if (p == NULL)
11085                                         goto badsub;
11086                                 subtype = p - types + VSNORMAL;
11087                                 break;
11088                         case '%':
11089                         case '#': {
11090                                 int cc = c;
11091                                 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11092                                 c = pgetc();
11093                                 if (c == cc)
11094                                         subtype++;
11095                                 else
11096                                         pungetc();
11097                                 break;
11098                         }
11099 #if ENABLE_ASH_BASH_COMPAT
11100                         case '/':
11101                                 subtype = VSREPLACE;
11102                                 c = pgetc();
11103                                 if (c == '/')
11104                                         subtype++; /* VSREPLACEALL */
11105                                 else
11106                                         pungetc();
11107                                 break;
11108 #endif
11109                         }
11110                 } else {
11111                         pungetc();
11112                 }
11113                 if (dblquote || arinest)
11114                         flags |= VSQUOTE;
11115                 *((char *)stackblock() + typeloc) = subtype | flags;
11116                 if (subtype != VSNORMAL) {
11117                         varnest++;
11118                         if (dblquote || arinest) {
11119                                 dqvarnest++;
11120                         }
11121                 }
11122         }
11123         goto parsesub_return;
11124 }
11125
11126 /*
11127  * Called to parse command substitutions.  Newstyle is set if the command
11128  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11129  * list of commands (passed by reference), and savelen is the number of
11130  * characters on the top of the stack which must be preserved.
11131  */
11132 parsebackq: {
11133         struct nodelist **nlpp;
11134         smallint savepbq;
11135         union node *n;
11136         char *volatile str;
11137         struct jmploc jmploc;
11138         struct jmploc *volatile savehandler;
11139         size_t savelen;
11140         smallint saveprompt = 0;
11141
11142 #ifdef __GNUC__
11143         (void) &saveprompt;
11144 #endif
11145         savepbq = parsebackquote;
11146         if (setjmp(jmploc.loc)) {
11147                 free(str);
11148                 parsebackquote = 0;
11149                 exception_handler = savehandler;
11150                 longjmp(exception_handler->loc, 1);
11151         }
11152         INT_OFF;
11153         str = NULL;
11154         savelen = out - (char *)stackblock();
11155         if (savelen > 0) {
11156                 str = ckmalloc(savelen);
11157                 memcpy(str, stackblock(), savelen);
11158         }
11159         savehandler = exception_handler;
11160         exception_handler = &jmploc;
11161         INT_ON;
11162         if (oldstyle) {
11163                 /* We must read until the closing backquote, giving special
11164                    treatment to some slashes, and then push the string and
11165                    reread it as input, interpreting it normally.  */
11166                 char *pout;
11167                 int pc;
11168                 size_t psavelen;
11169                 char *pstr;
11170
11171
11172                 STARTSTACKSTR(pout);
11173                 for (;;) {
11174                         if (needprompt) {
11175                                 setprompt(2);
11176                         }
11177                         pc = pgetc();
11178                         switch (pc) {
11179                         case '`':
11180                                 goto done;
11181
11182                         case '\\':
11183                                 pc = pgetc();
11184                                 if (pc == '\n') {
11185                                         g_parsefile->linno++;
11186                                         if (doprompt)
11187                                                 setprompt(2);
11188                                         /*
11189                                          * If eating a newline, avoid putting
11190                                          * the newline into the new character
11191                                          * stream (via the STPUTC after the
11192                                          * switch).
11193                                          */
11194                                         continue;
11195                                 }
11196                                 if (pc != '\\' && pc != '`' && pc != '$'
11197                                  && (!dblquote || pc != '"'))
11198                                         STPUTC('\\', pout);
11199                                 if (pc > PEOA_OR_PEOF) {
11200                                         break;
11201                                 }
11202                                 /* fall through */
11203
11204                         case PEOF:
11205 #if ENABLE_ASH_ALIAS
11206                         case PEOA:
11207 #endif
11208                                 startlinno = g_parsefile->linno;
11209                                 raise_error_syntax("EOF in backquote substitution");
11210
11211                         case '\n':
11212                                 g_parsefile->linno++;
11213                                 needprompt = doprompt;
11214                                 break;
11215
11216                         default:
11217                                 break;
11218                         }
11219                         STPUTC(pc, pout);
11220                 }
11221  done:
11222                 STPUTC('\0', pout);
11223                 psavelen = pout - (char *)stackblock();
11224                 if (psavelen > 0) {
11225                         pstr = grabstackstr(pout);
11226                         setinputstring(pstr);
11227                 }
11228         }
11229         nlpp = &bqlist;
11230         while (*nlpp)
11231                 nlpp = &(*nlpp)->next;
11232         *nlpp = stzalloc(sizeof(**nlpp));
11233         /* (*nlpp)->next = NULL; - stzalloc did it */
11234         parsebackquote = oldstyle;
11235
11236         if (oldstyle) {
11237                 saveprompt = doprompt;
11238                 doprompt = 0;
11239         }
11240
11241         n = list(2);
11242
11243         if (oldstyle)
11244                 doprompt = saveprompt;
11245         else if (readtoken() != TRP)
11246                 raise_error_unexpected_syntax(TRP);
11247
11248         (*nlpp)->n = n;
11249         if (oldstyle) {
11250                 /*
11251                  * Start reading from old file again, ignoring any pushed back
11252                  * tokens left from the backquote parsing
11253                  */
11254                 popfile();
11255                 tokpushback = 0;
11256         }
11257         while (stackblocksize() <= savelen)
11258                 growstackblock();
11259         STARTSTACKSTR(out);
11260         if (str) {
11261                 memcpy(out, str, savelen);
11262                 STADJUST(savelen, out);
11263                 INT_OFF;
11264                 free(str);
11265                 str = NULL;
11266                 INT_ON;
11267         }
11268         parsebackquote = savepbq;
11269         exception_handler = savehandler;
11270         if (arinest || dblquote)
11271                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11272         else
11273                 USTPUTC(CTLBACKQ, out);
11274         if (oldstyle)
11275                 goto parsebackq_oldreturn;
11276         goto parsebackq_newreturn;
11277 }
11278
11279 #if ENABLE_ASH_MATH_SUPPORT
11280 /*
11281  * Parse an arithmetic expansion (indicate start of one and set state)
11282  */
11283 parsearith: {
11284         if (++arinest == 1) {
11285                 prevsyntax = syntax;
11286                 syntax = ARISYNTAX;
11287                 USTPUTC(CTLARI, out);
11288                 if (dblquote)
11289                         USTPUTC('"', out);
11290                 else
11291                         USTPUTC(' ', out);
11292         } else {
11293                 /*
11294                  * we collapse embedded arithmetic expansion to
11295                  * parenthesis, which should be equivalent
11296                  */
11297                 USTPUTC('(', out);
11298         }
11299         goto parsearith_return;
11300 }
11301 #endif
11302
11303 } /* end of readtoken */
11304
11305 /*
11306  * Read the next input token.
11307  * If the token is a word, we set backquotelist to the list of cmds in
11308  *      backquotes.  We set quoteflag to true if any part of the word was
11309  *      quoted.
11310  * If the token is TREDIR, then we set redirnode to a structure containing
11311  *      the redirection.
11312  * In all cases, the variable startlinno is set to the number of the line
11313  *      on which the token starts.
11314  *
11315  * [Change comment:  here documents and internal procedures]
11316  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
11317  *  word parsing code into a separate routine.  In this case, readtoken
11318  *  doesn't need to have any internal procedures, but parseword does.
11319  *  We could also make parseoperator in essence the main routine, and
11320  *  have parseword (readtoken1?) handle both words and redirection.]
11321  */
11322 #define NEW_xxreadtoken
11323 #ifdef NEW_xxreadtoken
11324 /* singles must be first! */
11325 static const char xxreadtoken_chars[7] ALIGN1 = {
11326         '\n', '(', ')', /* singles */
11327         '&', '|', ';',  /* doubles */
11328         0
11329 };
11330
11331 #define xxreadtoken_singles 3
11332 #define xxreadtoken_doubles 3
11333
11334 static const char xxreadtoken_tokens[] ALIGN1 = {
11335         TNL, TLP, TRP,          /* only single occurrence allowed */
11336         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11337         TEOF,                   /* corresponds to trailing nul */
11338         TAND, TOR, TENDCASE     /* if double occurrence */
11339 };
11340
11341 static int
11342 xxreadtoken(void)
11343 {
11344         int c;
11345
11346         if (tokpushback) {
11347                 tokpushback = 0;
11348                 return lasttoken;
11349         }
11350         if (needprompt) {
11351                 setprompt(2);
11352         }
11353         startlinno = g_parsefile->linno;
11354         for (;;) {                      /* until token or start of word found */
11355                 c = pgetc_fast();
11356                 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11357                         continue;
11358
11359                 if (c == '#') {
11360                         while ((c = pgetc()) != '\n' && c != PEOF)
11361                                 continue;
11362                         pungetc();
11363                 } else if (c == '\\') {
11364                         if (pgetc() != '\n') {
11365                                 pungetc();
11366                                 break; /* return readtoken1(...) */
11367                         }
11368                         startlinno = ++g_parsefile->linno;
11369                         if (doprompt)
11370                                 setprompt(2);
11371                 } else {
11372                         const char *p;
11373
11374                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11375                         if (c != PEOF) {
11376                                 if (c == '\n') {
11377                                         g_parsefile->linno++;
11378                                         needprompt = doprompt;
11379                                 }
11380
11381                                 p = strchr(xxreadtoken_chars, c);
11382                                 if (p == NULL)
11383                                         break; /* return readtoken1(...) */
11384
11385                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11386                                         int cc = pgetc();
11387                                         if (cc == c) {    /* double occurrence? */
11388                                                 p += xxreadtoken_doubles + 1;
11389                                         } else {
11390                                                 pungetc();
11391 #if ENABLE_ASH_BASH_COMPAT
11392                                                 if (c == '&' && cc == '>') /* &> */
11393                                                         break; /* return readtoken1(...) */
11394 #endif
11395                                         }
11396                                 }
11397                         }
11398                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11399                         return lasttoken;
11400                 }
11401         } /* for (;;) */
11402
11403         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11404 }
11405 #else /* old xxreadtoken */
11406 #define RETURN(token)   return lasttoken = token
11407 static int
11408 xxreadtoken(void)
11409 {
11410         int c;
11411
11412         if (tokpushback) {
11413                 tokpushback = 0;
11414                 return lasttoken;
11415         }
11416         if (needprompt) {
11417                 setprompt(2);
11418         }
11419         startlinno = g_parsefile->linno;
11420         for (;;) {      /* until token or start of word found */
11421                 c = pgetc_fast();
11422                 switch (c) {
11423                 case ' ': case '\t':
11424 #if ENABLE_ASH_ALIAS
11425                 case PEOA:
11426 #endif
11427                         continue;
11428                 case '#':
11429                         while ((c = pgetc()) != '\n' && c != PEOF)
11430                                 continue;
11431                         pungetc();
11432                         continue;
11433                 case '\\':
11434                         if (pgetc() == '\n') {
11435                                 startlinno = ++g_parsefile->linno;
11436                                 if (doprompt)
11437                                         setprompt(2);
11438                                 continue;
11439                         }
11440                         pungetc();
11441                         goto breakloop;
11442                 case '\n':
11443                         g_parsefile->linno++;
11444                         needprompt = doprompt;
11445                         RETURN(TNL);
11446                 case PEOF:
11447                         RETURN(TEOF);
11448                 case '&':
11449                         if (pgetc() == '&')
11450                                 RETURN(TAND);
11451                         pungetc();
11452                         RETURN(TBACKGND);
11453                 case '|':
11454                         if (pgetc() == '|')
11455                                 RETURN(TOR);
11456                         pungetc();
11457                         RETURN(TPIPE);
11458                 case ';':
11459                         if (pgetc() == ';')
11460                                 RETURN(TENDCASE);
11461                         pungetc();
11462                         RETURN(TSEMI);
11463                 case '(':
11464                         RETURN(TLP);
11465                 case ')':
11466                         RETURN(TRP);
11467                 default:
11468                         goto breakloop;
11469                 }
11470         }
11471  breakloop:
11472         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11473 #undef RETURN
11474 }
11475 #endif /* old xxreadtoken */
11476
11477 static int
11478 readtoken(void)
11479 {
11480         int t;
11481 #if DEBUG
11482         smallint alreadyseen = tokpushback;
11483 #endif
11484
11485 #if ENABLE_ASH_ALIAS
11486  top:
11487 #endif
11488
11489         t = xxreadtoken();
11490
11491         /*
11492          * eat newlines
11493          */
11494         if (checkkwd & CHKNL) {
11495                 while (t == TNL) {
11496                         parseheredoc();
11497                         t = xxreadtoken();
11498                 }
11499         }
11500
11501         if (t != TWORD || quoteflag) {
11502                 goto out;
11503         }
11504
11505         /*
11506          * check for keywords
11507          */
11508         if (checkkwd & CHKKWD) {
11509                 const char *const *pp;
11510
11511                 pp = findkwd(wordtext);
11512                 if (pp) {
11513                         lasttoken = t = pp - tokname_array;
11514                         TRACE(("keyword %s recognized\n", tokname(t)));
11515                         goto out;
11516                 }
11517         }
11518
11519         if (checkkwd & CHKALIAS) {
11520 #if ENABLE_ASH_ALIAS
11521                 struct alias *ap;
11522                 ap = lookupalias(wordtext, 1);
11523                 if (ap != NULL) {
11524                         if (*ap->val) {
11525                                 pushstring(ap->val, ap);
11526                         }
11527                         goto top;
11528                 }
11529 #endif
11530         }
11531  out:
11532         checkkwd = 0;
11533 #if DEBUG
11534         if (!alreadyseen)
11535                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11536         else
11537                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11538 #endif
11539         return t;
11540 }
11541
11542 static char
11543 peektoken(void)
11544 {
11545         int t;
11546
11547         t = readtoken();
11548         tokpushback = 1;
11549         return tokname_array[t][0];
11550 }
11551
11552 /*
11553  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
11554  * valid parse tree indicating a blank line.)
11555  */
11556 static union node *
11557 parsecmd(int interact)
11558 {
11559         int t;
11560
11561         tokpushback = 0;
11562         doprompt = interact;
11563         if (doprompt)
11564                 setprompt(doprompt);
11565         needprompt = 0;
11566         t = readtoken();
11567         if (t == TEOF)
11568                 return NEOF;
11569         if (t == TNL)
11570                 return NULL;
11571         tokpushback = 1;
11572         return list(1);
11573 }
11574
11575 /*
11576  * Input any here documents.
11577  */
11578 static void
11579 parseheredoc(void)
11580 {
11581         struct heredoc *here;
11582         union node *n;
11583
11584         here = heredoclist;
11585         heredoclist = NULL;
11586
11587         while (here) {
11588                 if (needprompt) {
11589                         setprompt(2);
11590                 }
11591                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11592                                 here->eofmark, here->striptabs);
11593                 n = stzalloc(sizeof(struct narg));
11594                 n->narg.type = NARG;
11595                 /*n->narg.next = NULL; - stzalloc did it */
11596                 n->narg.text = wordtext;
11597                 n->narg.backquote = backquotelist;
11598                 here->here->nhere.doc = n;
11599                 here = here->next;
11600         }
11601 }
11602
11603
11604 /*
11605  * called by editline -- any expansions to the prompt should be added here.
11606  */
11607 #if ENABLE_ASH_EXPAND_PRMT
11608 static const char *
11609 expandstr(const char *ps)
11610 {
11611         union node n;
11612
11613         /* XXX Fix (char *) cast. */
11614         setinputstring((char *)ps);
11615         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11616         popfile();
11617
11618         n.narg.type = NARG;
11619         n.narg.next = NULL;
11620         n.narg.text = wordtext;
11621         n.narg.backquote = backquotelist;
11622
11623         expandarg(&n, NULL, 0);
11624         return stackblock();
11625 }
11626 #endif
11627
11628 /*
11629  * Execute a command or commands contained in a string.
11630  */
11631 static int
11632 evalstring(char *s, int mask)
11633 {
11634         union node *n;
11635         struct stackmark smark;
11636         int skip;
11637
11638         setinputstring(s);
11639         setstackmark(&smark);
11640
11641         skip = 0;
11642         while ((n = parsecmd(0)) != NEOF) {
11643                 evaltree(n, 0);
11644                 popstackmark(&smark);
11645                 skip = evalskip;
11646                 if (skip)
11647                         break;
11648         }
11649         popfile();
11650
11651         skip &= mask;
11652         evalskip = skip;
11653         return skip;
11654 }
11655
11656 /*
11657  * The eval command.
11658  */
11659 static int
11660 evalcmd(int argc UNUSED_PARAM, char **argv)
11661 {
11662         char *p;
11663         char *concat;
11664
11665         if (argv[1]) {
11666                 p = argv[1];
11667                 argv += 2;
11668                 if (argv[0]) {
11669                         STARTSTACKSTR(concat);
11670                         for (;;) {
11671                                 concat = stack_putstr(p, concat);
11672                                 p = *argv++;
11673                                 if (p == NULL)
11674                                         break;
11675                                 STPUTC(' ', concat);
11676                         }
11677                         STPUTC('\0', concat);
11678                         p = grabstackstr(concat);
11679                 }
11680                 evalstring(p, ~SKIPEVAL);
11681
11682         }
11683         return exitstatus;
11684 }
11685
11686 /*
11687  * Read and execute commands.  "Top" is nonzero for the top level command
11688  * loop; it turns on prompting if the shell is interactive.
11689  */
11690 static int
11691 cmdloop(int top)
11692 {
11693         union node *n;
11694         struct stackmark smark;
11695         int inter;
11696         int numeof = 0;
11697
11698         TRACE(("cmdloop(%d) called\n", top));
11699         for (;;) {
11700                 int skip;
11701
11702                 setstackmark(&smark);
11703 #if JOBS
11704                 if (doing_jobctl)
11705                         showjobs(stderr, SHOW_CHANGED);
11706 #endif
11707                 inter = 0;
11708                 if (iflag && top) {
11709                         inter++;
11710 #if ENABLE_ASH_MAIL
11711                         chkmail();
11712 #endif
11713                 }
11714                 n = parsecmd(inter);
11715                 /* showtree(n); DEBUG */
11716                 if (n == NEOF) {
11717                         if (!top || numeof >= 50)
11718                                 break;
11719                         if (!stoppedjobs()) {
11720                                 if (!Iflag)
11721                                         break;
11722                                 out2str("\nUse \"exit\" to leave shell.\n");
11723                         }
11724                         numeof++;
11725                 } else if (nflag == 0) {
11726                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11727                         job_warning >>= 1;
11728                         numeof = 0;
11729                         evaltree(n, 0);
11730                 }
11731                 popstackmark(&smark);
11732                 skip = evalskip;
11733
11734                 if (skip) {
11735                         evalskip = 0;
11736                         return skip & SKIPEVAL;
11737                 }
11738         }
11739         return 0;
11740 }
11741
11742 /*
11743  * Take commands from a file.  To be compatible we should do a path
11744  * search for the file, which is necessary to find sub-commands.
11745  */
11746 static char *
11747 find_dot_file(char *name)
11748 {
11749         char *fullname;
11750         const char *path = pathval();
11751         struct stat statb;
11752
11753         /* don't try this for absolute or relative paths */
11754         if (strchr(name, '/'))
11755                 return name;
11756
11757         while ((fullname = padvance(&path, name)) != NULL) {
11758                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11759                         /*
11760                          * Don't bother freeing here, since it will
11761                          * be freed by the caller.
11762                          */
11763                         return fullname;
11764                 }
11765                 stunalloc(fullname);
11766         }
11767
11768         /* not found in the PATH */
11769         ash_msg_and_raise_error("%s: not found", name);
11770         /* NOTREACHED */
11771 }
11772
11773 static int
11774 dotcmd(int argc, char **argv)
11775 {
11776         struct strlist *sp;
11777         volatile struct shparam saveparam;
11778         int status = 0;
11779
11780         for (sp = cmdenviron; sp; sp = sp->next)
11781                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11782
11783         if (argv[1]) {        /* That's what SVR2 does */
11784                 char *fullname = find_dot_file(argv[1]);
11785                 argv += 2;
11786                 argc -= 2;
11787                 if (argc) { /* argc > 0, argv[0] != NULL */
11788                         saveparam = shellparam;
11789                         shellparam.malloced = 0;
11790                         shellparam.nparam = argc;
11791                         shellparam.p = argv;
11792                 };
11793
11794                 setinputfile(fullname, INPUT_PUSH_FILE);
11795                 commandname = fullname;
11796                 cmdloop(0);
11797                 popfile();
11798
11799                 if (argc) {
11800                         freeparam(&shellparam);
11801                         shellparam = saveparam;
11802                 };
11803                 status = exitstatus;
11804         }
11805         return status;
11806 }
11807
11808 static int
11809 exitcmd(int argc UNUSED_PARAM, char **argv)
11810 {
11811         if (stoppedjobs())
11812                 return 0;
11813         if (argv[1])
11814                 exitstatus = number(argv[1]);
11815         raise_exception(EXEXIT);
11816         /* NOTREACHED */
11817 }
11818
11819 /*
11820  * Read a file containing shell functions.
11821  */
11822 static void
11823 readcmdfile(char *name)
11824 {
11825         setinputfile(name, INPUT_PUSH_FILE);
11826         cmdloop(0);
11827         popfile();
11828 }
11829
11830
11831 /* ============ find_command inplementation */
11832
11833 /*
11834  * Resolve a command name.  If you change this routine, you may have to
11835  * change the shellexec routine as well.
11836  */
11837 static void
11838 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11839 {
11840         struct tblentry *cmdp;
11841         int idx;
11842         int prev;
11843         char *fullname;
11844         struct stat statb;
11845         int e;
11846         int updatetbl;
11847         struct builtincmd *bcmd;
11848
11849         /* If name contains a slash, don't use PATH or hash table */
11850         if (strchr(name, '/') != NULL) {
11851                 entry->u.index = -1;
11852                 if (act & DO_ABS) {
11853                         while (stat(name, &statb) < 0) {
11854 #ifdef SYSV
11855                                 if (errno == EINTR)
11856                                         continue;
11857 #endif
11858                                 entry->cmdtype = CMDUNKNOWN;
11859                                 return;
11860                         }
11861                 }
11862                 entry->cmdtype = CMDNORMAL;
11863                 return;
11864         }
11865
11866 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11867
11868         updatetbl = (path == pathval());
11869         if (!updatetbl) {
11870                 act |= DO_ALTPATH;
11871                 if (strstr(path, "%builtin") != NULL)
11872                         act |= DO_ALTBLTIN;
11873         }
11874
11875         /* If name is in the table, check answer will be ok */
11876         cmdp = cmdlookup(name, 0);
11877         if (cmdp != NULL) {
11878                 int bit;
11879
11880                 switch (cmdp->cmdtype) {
11881                 default:
11882 #if DEBUG
11883                         abort();
11884 #endif
11885                 case CMDNORMAL:
11886                         bit = DO_ALTPATH;
11887                         break;
11888                 case CMDFUNCTION:
11889                         bit = DO_NOFUNC;
11890                         break;
11891                 case CMDBUILTIN:
11892                         bit = DO_ALTBLTIN;
11893                         break;
11894                 }
11895                 if (act & bit) {
11896                         updatetbl = 0;
11897                         cmdp = NULL;
11898                 } else if (cmdp->rehash == 0)
11899                         /* if not invalidated by cd, we're done */
11900                         goto success;
11901         }
11902
11903         /* If %builtin not in path, check for builtin next */
11904         bcmd = find_builtin(name);
11905         if (bcmd) {
11906                 if (IS_BUILTIN_REGULAR(bcmd))
11907                         goto builtin_success;
11908                 if (act & DO_ALTPATH) {
11909                         if (!(act & DO_ALTBLTIN))
11910                                 goto builtin_success;
11911                 } else if (builtinloc <= 0) {
11912                         goto builtin_success;
11913                 }
11914         }
11915
11916 #if ENABLE_FEATURE_SH_STANDALONE
11917         {
11918                 int applet_no = find_applet_by_name(name);
11919                 if (applet_no >= 0) {
11920                         entry->cmdtype = CMDNORMAL;
11921                         entry->u.index = -2 - applet_no;
11922                         return;
11923                 }
11924         }
11925 #endif
11926
11927         /* We have to search path. */
11928         prev = -1;              /* where to start */
11929         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11930                 if (cmdp->cmdtype == CMDBUILTIN)
11931                         prev = builtinloc;
11932                 else
11933                         prev = cmdp->param.index;
11934         }
11935
11936         e = ENOENT;
11937         idx = -1;
11938  loop:
11939         while ((fullname = padvance(&path, name)) != NULL) {
11940                 stunalloc(fullname);
11941                 /* NB: code below will still use fullname
11942                  * despite it being "unallocated" */
11943                 idx++;
11944                 if (pathopt) {
11945                         if (prefix(pathopt, "builtin")) {
11946                                 if (bcmd)
11947                                         goto builtin_success;
11948                                 continue;
11949                         }
11950                         if ((act & DO_NOFUNC)
11951                          || !prefix(pathopt, "func")
11952                         ) {     /* ignore unimplemented options */
11953                                 continue;
11954                         }
11955                 }
11956                 /* if rehash, don't redo absolute path names */
11957                 if (fullname[0] == '/' && idx <= prev) {
11958                         if (idx < prev)
11959                                 continue;
11960                         TRACE(("searchexec \"%s\": no change\n", name));
11961                         goto success;
11962                 }
11963                 while (stat(fullname, &statb) < 0) {
11964 #ifdef SYSV
11965                         if (errno == EINTR)
11966                                 continue;
11967 #endif
11968                         if (errno != ENOENT && errno != ENOTDIR)
11969                                 e = errno;
11970                         goto loop;
11971                 }
11972                 e = EACCES;     /* if we fail, this will be the error */
11973                 if (!S_ISREG(statb.st_mode))
11974                         continue;
11975                 if (pathopt) {          /* this is a %func directory */
11976                         stalloc(strlen(fullname) + 1);
11977                         /* NB: stalloc will return space pointed by fullname
11978                          * (because we don't have any intervening allocations
11979                          * between stunalloc above and this stalloc) */
11980                         readcmdfile(fullname);
11981                         cmdp = cmdlookup(name, 0);
11982                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11983                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11984                         stunalloc(fullname);
11985                         goto success;
11986                 }
11987                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11988                 if (!updatetbl) {
11989                         entry->cmdtype = CMDNORMAL;
11990                         entry->u.index = idx;
11991                         return;
11992                 }
11993                 INT_OFF;
11994                 cmdp = cmdlookup(name, 1);
11995                 cmdp->cmdtype = CMDNORMAL;
11996                 cmdp->param.index = idx;
11997                 INT_ON;
11998                 goto success;
11999         }
12000
12001         /* We failed.  If there was an entry for this command, delete it */
12002         if (cmdp && updatetbl)
12003                 delete_cmd_entry();
12004         if (act & DO_ERR)
12005                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12006         entry->cmdtype = CMDUNKNOWN;
12007         return;
12008
12009  builtin_success:
12010         if (!updatetbl) {
12011                 entry->cmdtype = CMDBUILTIN;
12012                 entry->u.cmd = bcmd;
12013                 return;
12014         }
12015         INT_OFF;
12016         cmdp = cmdlookup(name, 1);
12017         cmdp->cmdtype = CMDBUILTIN;
12018         cmdp->param.cmd = bcmd;
12019         INT_ON;
12020  success:
12021         cmdp->rehash = 0;
12022         entry->cmdtype = cmdp->cmdtype;
12023         entry->u = cmdp->param;
12024 }
12025
12026
12027 /* ============ trap.c */
12028
12029 /*
12030  * The trap builtin.
12031  */
12032 static int
12033 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12034 {
12035         char *action;
12036         char **ap;
12037         int signo;
12038
12039         nextopt(nullstr);
12040         ap = argptr;
12041         if (!*ap) {
12042                 for (signo = 0; signo < NSIG; signo++) {
12043                         if (trap[signo] != NULL) {
12044                                 out1fmt("trap -- %s %s\n",
12045                                                 single_quote(trap[signo]),
12046                                                 get_signame(signo));
12047                         }
12048                 }
12049                 return 0;
12050         }
12051         action = NULL;
12052         if (ap[1])
12053                 action = *ap++;
12054         while (*ap) {
12055                 signo = get_signum(*ap);
12056                 if (signo < 0)
12057                         ash_msg_and_raise_error("%s: bad trap", *ap);
12058                 INT_OFF;
12059                 if (action) {
12060                         if (LONE_DASH(action))
12061                                 action = NULL;
12062                         else
12063                                 action = ckstrdup(action);
12064                 }
12065                 free(trap[signo]);
12066                 trap[signo] = action;
12067                 if (signo != 0)
12068                         setsignal(signo);
12069                 INT_ON;
12070                 ap++;
12071         }
12072         return 0;
12073 }
12074
12075
12076 /* ============ Builtins */
12077
12078 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12079 /*
12080  * Lists available builtins
12081  */
12082 static int
12083 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12084 {
12085         unsigned col;
12086         unsigned i;
12087
12088         out1fmt("\nBuilt-in commands:\n-------------------\n");
12089         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12090                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12091                                         builtintab[i].name + 1);
12092                 if (col > 60) {
12093                         out1fmt("\n");
12094                         col = 0;
12095                 }
12096         }
12097 #if ENABLE_FEATURE_SH_STANDALONE
12098         {
12099                 const char *a = applet_names;
12100                 while (*a) {
12101                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12102                         if (col > 60) {
12103                                 out1fmt("\n");
12104                                 col = 0;
12105                         }
12106                         a += strlen(a) + 1;
12107                 }
12108         }
12109 #endif
12110         out1fmt("\n\n");
12111         return EXIT_SUCCESS;
12112 }
12113 #endif /* FEATURE_SH_EXTRA_QUIET */
12114
12115 /*
12116  * The export and readonly commands.
12117  */
12118 static int
12119 exportcmd(int argc UNUSED_PARAM, char **argv)
12120 {
12121         struct var *vp;
12122         char *name;
12123         const char *p;
12124         char **aptr;
12125         int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12126
12127         if (nextopt("p") != 'p') {
12128                 aptr = argptr;
12129                 name = *aptr;
12130                 if (name) {
12131                         do {
12132                                 p = strchr(name, '=');
12133                                 if (p != NULL) {
12134                                         p++;
12135                                 } else {
12136                                         vp = *findvar(hashvar(name), name);
12137                                         if (vp) {
12138                                                 vp->flags |= flag;
12139                                                 continue;
12140                                         }
12141                                 }
12142                                 setvar(name, p, flag);
12143                         } while ((name = *++aptr) != NULL);
12144                         return 0;
12145                 }
12146         }
12147         showvars(argv[0], flag, 0);
12148         return 0;
12149 }
12150
12151 /*
12152  * Delete a function if it exists.
12153  */
12154 static void
12155 unsetfunc(const char *name)
12156 {
12157         struct tblentry *cmdp;
12158
12159         cmdp = cmdlookup(name, 0);
12160         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12161                 delete_cmd_entry();
12162 }
12163
12164 /*
12165  * The unset builtin command.  We unset the function before we unset the
12166  * variable to allow a function to be unset when there is a readonly variable
12167  * with the same name.
12168  */
12169 static int
12170 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12171 {
12172         char **ap;
12173         int i;
12174         int flag = 0;
12175         int ret = 0;
12176
12177         while ((i = nextopt("vf")) != '\0') {
12178                 flag = i;
12179         }
12180
12181         for (ap = argptr; *ap; ap++) {
12182                 if (flag != 'f') {
12183                         i = unsetvar(*ap);
12184                         ret |= i;
12185                         if (!(i & 2))
12186                                 continue;
12187                 }
12188                 if (flag != 'v')
12189                         unsetfunc(*ap);
12190         }
12191         return ret & 1;
12192 }
12193
12194
12195 /*      setmode.c      */
12196
12197 #include <sys/times.h>
12198
12199 static const unsigned char timescmd_str[] ALIGN1 = {
12200         ' ',  offsetof(struct tms, tms_utime),
12201         '\n', offsetof(struct tms, tms_stime),
12202         ' ',  offsetof(struct tms, tms_cutime),
12203         '\n', offsetof(struct tms, tms_cstime),
12204         0
12205 };
12206
12207 static int
12208 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12209 {
12210         long clk_tck, s, t;
12211         const unsigned char *p;
12212         struct tms buf;
12213
12214         clk_tck = sysconf(_SC_CLK_TCK);
12215         times(&buf);
12216
12217         p = timescmd_str;
12218         do {
12219                 t = *(clock_t *)(((char *) &buf) + p[1]);
12220                 s = t / clk_tck;
12221                 out1fmt("%ldm%ld.%.3lds%c",
12222                         s/60, s%60,
12223                         ((t - s * clk_tck) * 1000) / clk_tck,
12224                         p[0]);
12225         } while (*(p += 2));
12226
12227         return 0;
12228 }
12229
12230 #if ENABLE_ASH_MATH_SUPPORT
12231 static arith_t
12232 dash_arith(const char *s)
12233 {
12234         arith_t result;
12235         int errcode = 0;
12236
12237         INT_OFF;
12238         result = arith(s, &errcode);
12239         if (errcode < 0) {
12240                 if (errcode == -3)
12241                         ash_msg_and_raise_error("exponent less than 0");
12242                 if (errcode == -2)
12243                         ash_msg_and_raise_error("divide by zero");
12244                 if (errcode == -5)
12245                         ash_msg_and_raise_error("expression recursion loop detected");
12246                 raise_error_syntax(s);
12247         }
12248         INT_ON;
12249
12250         return result;
12251 }
12252
12253 /*
12254  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12255  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12256  *
12257  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12258  */
12259 static int
12260 letcmd(int argc UNUSED_PARAM, char **argv)
12261 {
12262         arith_t i;
12263
12264         argv++;
12265         if (!*argv)
12266                 ash_msg_and_raise_error("expression expected");
12267         do {
12268                 i = dash_arith(*argv);
12269         } while (*++argv);
12270
12271         return !i;
12272 }
12273 #endif /* ASH_MATH_SUPPORT */
12274
12275
12276 /* ============ miscbltin.c
12277  *
12278  * Miscellaneous builtins.
12279  */
12280
12281 #undef rflag
12282
12283 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12284 typedef enum __rlimit_resource rlim_t;
12285 #endif
12286
12287 /*
12288  * The read builtin. Options:
12289  *      -r              Do not interpret '\' specially
12290  *      -s              Turn off echo (tty only)
12291  *      -n NCHARS       Read NCHARS max
12292  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12293  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12294  *      -u FD           Read from given FD instead of fd 0
12295  * This uses unbuffered input, which may be avoidable in some cases.
12296  * TODO: bash also has:
12297  *      -a ARRAY        Read into array[0],[1],etc
12298  *      -d DELIM        End on DELIM char, not newline
12299  *      -e              Use line editing (tty only)
12300  */
12301 static int
12302 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12303 {
12304         static const char *const arg_REPLY[] = { "REPLY", NULL };
12305
12306         char **ap;
12307         int backslash;
12308         char c;
12309         int rflag;
12310         char *prompt;
12311         const char *ifs;
12312         char *p;
12313         int startword;
12314         int status;
12315         int i;
12316         int fd = 0;
12317 #if ENABLE_ASH_READ_NCHARS
12318         int nchars = 0; /* if != 0, -n is in effect */
12319         int silent = 0;
12320         struct termios tty, old_tty;
12321 #endif
12322 #if ENABLE_ASH_READ_TIMEOUT
12323         unsigned end_ms = 0;
12324         unsigned timeout = 0;
12325 #endif
12326
12327         rflag = 0;
12328         prompt = NULL;
12329         while ((i = nextopt("p:u:r"
12330                 USE_ASH_READ_TIMEOUT("t:")
12331                 USE_ASH_READ_NCHARS("n:s")
12332         )) != '\0') {
12333                 switch (i) {
12334                 case 'p':
12335                         prompt = optionarg;
12336                         break;
12337 #if ENABLE_ASH_READ_NCHARS
12338                 case 'n':
12339                         nchars = bb_strtou(optionarg, NULL, 10);
12340                         if (nchars < 0 || errno)
12341                                 ash_msg_and_raise_error("invalid count");
12342                         /* nchars == 0: off (bash 3.2 does this too) */
12343                         break;
12344                 case 's':
12345                         silent = 1;
12346                         break;
12347 #endif
12348 #if ENABLE_ASH_READ_TIMEOUT
12349                 case 't':
12350                         timeout = bb_strtou(optionarg, NULL, 10);
12351                         if (errno || timeout > UINT_MAX / 2048)
12352                                 ash_msg_and_raise_error("invalid timeout");
12353                         timeout *= 1000;
12354 #if 0 /* even bash have no -t N.NNN support */
12355                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
12356                         ts.tv_usec = 0;
12357                         /* EINVAL means number is ok, but not terminated by NUL */
12358                         if (*p == '.' && errno == EINVAL) {
12359                                 char *p2;
12360                                 if (*++p) {
12361                                         int scale;
12362                                         ts.tv_usec = bb_strtou(p, &p2, 10);
12363                                         if (errno)
12364                                                 ash_msg_and_raise_error("invalid timeout");
12365                                         scale = p2 - p;
12366                                         /* normalize to usec */
12367                                         if (scale > 6)
12368                                                 ash_msg_and_raise_error("invalid timeout");
12369                                         while (scale++ < 6)
12370                                                 ts.tv_usec *= 10;
12371                                 }
12372                         } else if (ts.tv_sec < 0 || errno) {
12373                                 ash_msg_and_raise_error("invalid timeout");
12374                         }
12375                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12376                                 ash_msg_and_raise_error("invalid timeout");
12377                         }
12378 #endif /* if 0 */
12379                         break;
12380 #endif
12381                 case 'r':
12382                         rflag = 1;
12383                         break;
12384                 case 'u':
12385                         fd = bb_strtou(optionarg, NULL, 10);
12386                         if (fd < 0 || errno)
12387                                 ash_msg_and_raise_error("invalid file descriptor");
12388                         break;
12389                 default:
12390                         break;
12391                 }
12392         }
12393         if (prompt && isatty(fd)) {
12394                 out2str(prompt);
12395         }
12396         ap = argptr;
12397         if (*ap == NULL)
12398                 ap = (char**)arg_REPLY;
12399         ifs = bltinlookup("IFS");
12400         if (ifs == NULL)
12401                 ifs = defifs;
12402 #if ENABLE_ASH_READ_NCHARS
12403         tcgetattr(fd, &tty);
12404         old_tty = tty;
12405         if (nchars || silent) {
12406                 if (nchars) {
12407                         tty.c_lflag &= ~ICANON;
12408                         tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12409                 }
12410                 if (silent) {
12411                         tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12412                 }
12413                 /* if tcgetattr failed, tcsetattr will fail too.
12414                  * Ignoring, it's harmless. */
12415                 tcsetattr(fd, TCSANOW, &tty);
12416         }
12417 #endif
12418
12419         status = 0;
12420         startword = 1;
12421         backslash = 0;
12422 #if ENABLE_ASH_READ_TIMEOUT
12423         if (timeout) /* NB: ensuring end_ms is nonzero */
12424                 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12425 #endif
12426         STARTSTACKSTR(p);
12427         do {
12428 #if ENABLE_ASH_READ_TIMEOUT
12429                 if (end_ms) {
12430                         struct pollfd pfd[1];
12431                         pfd[0].fd = fd;
12432                         pfd[0].events = POLLIN;
12433                         timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12434                         if ((int)timeout <= 0 /* already late? */
12435                          || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12436                         ) { /* timed out! */
12437 #if ENABLE_ASH_READ_NCHARS
12438                                 tcsetattr(fd, TCSANOW, &old_tty);
12439 #endif
12440                                 return 1;
12441                         }
12442                 }
12443 #endif
12444                 if (nonblock_safe_read(fd, &c, 1) != 1) {
12445                         status = 1;
12446                         break;
12447                 }
12448                 if (c == '\0')
12449                         continue;
12450                 if (backslash) {
12451                         backslash = 0;
12452                         if (c != '\n')
12453                                 goto put;
12454                         continue;
12455                 }
12456                 if (!rflag && c == '\\') {
12457                         backslash++;
12458                         continue;
12459                 }
12460                 if (c == '\n')
12461                         break;
12462                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12463                         continue;
12464                 }
12465                 startword = 0;
12466                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12467                         STACKSTRNUL(p);
12468                         setvar(*ap, stackblock(), 0);
12469                         ap++;
12470                         startword = 1;
12471                         STARTSTACKSTR(p);
12472                 } else {
12473  put:
12474                         STPUTC(c, p);
12475                 }
12476         }
12477 /* end of do {} while: */
12478 #if ENABLE_ASH_READ_NCHARS
12479         while (--nchars);
12480 #else
12481         while (1);
12482 #endif
12483
12484 #if ENABLE_ASH_READ_NCHARS
12485         tcsetattr(fd, TCSANOW, &old_tty);
12486 #endif
12487
12488         STACKSTRNUL(p);
12489         /* Remove trailing blanks */
12490         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12491                 *p = '\0';
12492         setvar(*ap, stackblock(), 0);
12493         while (*++ap != NULL)
12494                 setvar(*ap, nullstr, 0);
12495         return status;
12496 }
12497
12498 static int
12499 umaskcmd(int argc UNUSED_PARAM, char **argv)
12500 {
12501         static const char permuser[3] ALIGN1 = "ugo";
12502         static const char permmode[3] ALIGN1 = "rwx";
12503         static const short permmask[] ALIGN2 = {
12504                 S_IRUSR, S_IWUSR, S_IXUSR,
12505                 S_IRGRP, S_IWGRP, S_IXGRP,
12506                 S_IROTH, S_IWOTH, S_IXOTH
12507         };
12508
12509         char *ap;
12510         mode_t mask;
12511         int i;
12512         int symbolic_mode = 0;
12513
12514         while (nextopt("S") != '\0') {
12515                 symbolic_mode = 1;
12516         }
12517
12518         INT_OFF;
12519         mask = umask(0);
12520         umask(mask);
12521         INT_ON;
12522
12523         ap = *argptr;
12524         if (ap == NULL) {
12525                 if (symbolic_mode) {
12526                         char buf[18];
12527                         char *p = buf;
12528
12529                         for (i = 0; i < 3; i++) {
12530                                 int j;
12531
12532                                 *p++ = permuser[i];
12533                                 *p++ = '=';
12534                                 for (j = 0; j < 3; j++) {
12535                                         if ((mask & permmask[3 * i + j]) == 0) {
12536                                                 *p++ = permmode[j];
12537                                         }
12538                                 }
12539                                 *p++ = ',';
12540                         }
12541                         *--p = 0;
12542                         puts(buf);
12543                 } else {
12544                         out1fmt("%.4o\n", mask);
12545                 }
12546         } else {
12547                 if (isdigit((unsigned char) *ap)) {
12548                         mask = 0;
12549                         do {
12550                                 if (*ap >= '8' || *ap < '0')
12551                                         ash_msg_and_raise_error(illnum, argv[1]);
12552                                 mask = (mask << 3) + (*ap - '0');
12553                         } while (*++ap != '\0');
12554                         umask(mask);
12555                 } else {
12556                         mask = ~mask & 0777;
12557                         if (!bb_parse_mode(ap, &mask)) {
12558                                 ash_msg_and_raise_error("illegal mode: %s", ap);
12559                         }
12560                         umask(~mask & 0777);
12561                 }
12562         }
12563         return 0;
12564 }
12565
12566 /*
12567  * ulimit builtin
12568  *
12569  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12570  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12571  * ash by J.T. Conklin.
12572  *
12573  * Public domain.
12574  */
12575
12576 struct limits {
12577         uint8_t cmd;          /* RLIMIT_xxx fit into it */
12578         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12579         char    option;
12580 };
12581
12582 static const struct limits limits_tbl[] = {
12583 #ifdef RLIMIT_CPU
12584         { RLIMIT_CPU,        0, 't' },
12585 #endif
12586 #ifdef RLIMIT_FSIZE
12587         { RLIMIT_FSIZE,      9, 'f' },
12588 #endif
12589 #ifdef RLIMIT_DATA
12590         { RLIMIT_DATA,      10, 'd' },
12591 #endif
12592 #ifdef RLIMIT_STACK
12593         { RLIMIT_STACK,     10, 's' },
12594 #endif
12595 #ifdef RLIMIT_CORE
12596         { RLIMIT_CORE,       9, 'c' },
12597 #endif
12598 #ifdef RLIMIT_RSS
12599         { RLIMIT_RSS,       10, 'm' },
12600 #endif
12601 #ifdef RLIMIT_MEMLOCK
12602         { RLIMIT_MEMLOCK,   10, 'l' },
12603 #endif
12604 #ifdef RLIMIT_NPROC
12605         { RLIMIT_NPROC,      0, 'p' },
12606 #endif
12607 #ifdef RLIMIT_NOFILE
12608         { RLIMIT_NOFILE,     0, 'n' },
12609 #endif
12610 #ifdef RLIMIT_AS
12611         { RLIMIT_AS,        10, 'v' },
12612 #endif
12613 #ifdef RLIMIT_LOCKS
12614         { RLIMIT_LOCKS,      0, 'w' },
12615 #endif
12616 };
12617 static const char limits_name[] =
12618 #ifdef RLIMIT_CPU
12619         "time(seconds)" "\0"
12620 #endif
12621 #ifdef RLIMIT_FSIZE
12622         "file(blocks)" "\0"
12623 #endif
12624 #ifdef RLIMIT_DATA
12625         "data(kb)" "\0"
12626 #endif
12627 #ifdef RLIMIT_STACK
12628         "stack(kb)" "\0"
12629 #endif
12630 #ifdef RLIMIT_CORE
12631         "coredump(blocks)" "\0"
12632 #endif
12633 #ifdef RLIMIT_RSS
12634         "memory(kb)" "\0"
12635 #endif
12636 #ifdef RLIMIT_MEMLOCK
12637         "locked memory(kb)" "\0"
12638 #endif
12639 #ifdef RLIMIT_NPROC
12640         "process" "\0"
12641 #endif
12642 #ifdef RLIMIT_NOFILE
12643         "nofiles" "\0"
12644 #endif
12645 #ifdef RLIMIT_AS
12646         "vmemory(kb)" "\0"
12647 #endif
12648 #ifdef RLIMIT_LOCKS
12649         "locks" "\0"
12650 #endif
12651 ;
12652
12653 enum limtype { SOFT = 0x1, HARD = 0x2 };
12654
12655 static void
12656 printlim(enum limtype how, const struct rlimit *limit,
12657                         const struct limits *l)
12658 {
12659         rlim_t val;
12660
12661         val = limit->rlim_max;
12662         if (how & SOFT)
12663                 val = limit->rlim_cur;
12664
12665         if (val == RLIM_INFINITY)
12666                 out1fmt("unlimited\n");
12667         else {
12668                 val >>= l->factor_shift;
12669                 out1fmt("%lld\n", (long long) val);
12670         }
12671 }
12672
12673 static int
12674 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12675 {
12676         int c;
12677         rlim_t val = 0;
12678         enum limtype how = SOFT | HARD;
12679         const struct limits *l;
12680         int set, all = 0;
12681         int optc, what;
12682         struct rlimit limit;
12683
12684         what = 'f';
12685         while ((optc = nextopt("HSa"
12686 #ifdef RLIMIT_CPU
12687                                 "t"
12688 #endif
12689 #ifdef RLIMIT_FSIZE
12690                                 "f"
12691 #endif
12692 #ifdef RLIMIT_DATA
12693                                 "d"
12694 #endif
12695 #ifdef RLIMIT_STACK
12696                                 "s"
12697 #endif
12698 #ifdef RLIMIT_CORE
12699                                 "c"
12700 #endif
12701 #ifdef RLIMIT_RSS
12702                                 "m"
12703 #endif
12704 #ifdef RLIMIT_MEMLOCK
12705                                 "l"
12706 #endif
12707 #ifdef RLIMIT_NPROC
12708                                 "p"
12709 #endif
12710 #ifdef RLIMIT_NOFILE
12711                                 "n"
12712 #endif
12713 #ifdef RLIMIT_AS
12714                                 "v"
12715 #endif
12716 #ifdef RLIMIT_LOCKS
12717                                 "w"
12718 #endif
12719                                         )) != '\0')
12720                 switch (optc) {
12721                 case 'H':
12722                         how = HARD;
12723                         break;
12724                 case 'S':
12725                         how = SOFT;
12726                         break;
12727                 case 'a':
12728                         all = 1;
12729                         break;
12730                 default:
12731                         what = optc;
12732                 }
12733
12734         for (l = limits_tbl; l->option != what; l++)
12735                 continue;
12736
12737         set = *argptr ? 1 : 0;
12738         if (set) {
12739                 char *p = *argptr;
12740
12741                 if (all || argptr[1])
12742                         ash_msg_and_raise_error("too many arguments");
12743                 if (strncmp(p, "unlimited\n", 9) == 0)
12744                         val = RLIM_INFINITY;
12745                 else {
12746                         val = (rlim_t) 0;
12747
12748                         while ((c = *p++) >= '0' && c <= '9') {
12749                                 val = (val * 10) + (long)(c - '0');
12750                                 // val is actually 'unsigned long int' and can't get < 0
12751                                 if (val < (rlim_t) 0)
12752                                         break;
12753                         }
12754                         if (c)
12755                                 ash_msg_and_raise_error("bad number");
12756                         val <<= l->factor_shift;
12757                 }
12758         }
12759         if (all) {
12760                 const char *lname = limits_name;
12761                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12762                         getrlimit(l->cmd, &limit);
12763                         out1fmt("%-20s ", lname);
12764                         lname += strlen(lname) + 1;
12765                         printlim(how, &limit, l);
12766                 }
12767                 return 0;
12768         }
12769
12770         getrlimit(l->cmd, &limit);
12771         if (set) {
12772                 if (how & HARD)
12773                         limit.rlim_max = val;
12774                 if (how & SOFT)
12775                         limit.rlim_cur = val;
12776                 if (setrlimit(l->cmd, &limit) < 0)
12777                         ash_msg_and_raise_error("error setting limit (%m)");
12778         } else {
12779                 printlim(how, &limit, l);
12780         }
12781         return 0;
12782 }
12783
12784
12785 /* ============ Math support */
12786
12787 #if ENABLE_ASH_MATH_SUPPORT
12788
12789 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12790
12791    Permission is hereby granted, free of charge, to any person obtaining
12792    a copy of this software and associated documentation files (the
12793    "Software"), to deal in the Software without restriction, including
12794    without limitation the rights to use, copy, modify, merge, publish,
12795    distribute, sublicense, and/or sell copies of the Software, and to
12796    permit persons to whom the Software is furnished to do so, subject to
12797    the following conditions:
12798
12799    The above copyright notice and this permission notice shall be
12800    included in all copies or substantial portions of the Software.
12801
12802    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12803    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12804    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12805    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12806    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12807    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12808    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12809 */
12810
12811 /* This is my infix parser/evaluator. It is optimized for size, intended
12812  * as a replacement for yacc-based parsers. However, it may well be faster
12813  * than a comparable parser written in yacc. The supported operators are
12814  * listed in #defines below. Parens, order of operations, and error handling
12815  * are supported. This code is thread safe. The exact expression format should
12816  * be that which POSIX specifies for shells. */
12817
12818 /* The code uses a simple two-stack algorithm. See
12819  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12820  * for a detailed explanation of the infix-to-postfix algorithm on which
12821  * this is based (this code differs in that it applies operators immediately
12822  * to the stack instead of adding them to a queue to end up with an
12823  * expression). */
12824
12825 /* To use the routine, call it with an expression string and error return
12826  * pointer */
12827
12828 /*
12829  * Aug 24, 2001              Manuel Novoa III
12830  *
12831  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12832  *
12833  * 1) In arith_apply():
12834  *    a) Cached values of *numptr and &(numptr[-1]).
12835  *    b) Removed redundant test for zero denominator.
12836  *
12837  * 2) In arith():
12838  *    a) Eliminated redundant code for processing operator tokens by moving
12839  *       to a table-based implementation.  Also folded handling of parens
12840  *       into the table.
12841  *    b) Combined all 3 loops which called arith_apply to reduce generated
12842  *       code size at the cost of speed.
12843  *
12844  * 3) The following expressions were treated as valid by the original code:
12845  *       1()  ,    0!  ,    1 ( *3 )   .
12846  *    These bugs have been fixed by internally enclosing the expression in
12847  *    parens and then checking that all binary ops and right parens are
12848  *    preceded by a valid expression (NUM_TOKEN).
12849  *
12850  * Note: It may be desirable to replace Aaron's test for whitespace with
12851  * ctype's isspace() if it is used by another busybox applet or if additional
12852  * whitespace chars should be considered.  Look below the "#include"s for a
12853  * precompiler test.
12854  */
12855
12856 /*
12857  * Aug 26, 2001              Manuel Novoa III
12858  *
12859  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12860  *
12861  * Merge in Aaron's comments previously posted to the busybox list,
12862  * modified slightly to take account of my changes to the code.
12863  *
12864  */
12865
12866 /*
12867  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12868  *
12869  * - allow access to variable,
12870  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12871  * - realize assign syntax (VAR=expr, +=, *= etc)
12872  * - realize exponentiation (** operator)
12873  * - realize comma separated - expr, expr
12874  * - realise ++expr --expr expr++ expr--
12875  * - realise expr ? expr : expr (but, second expr calculate always)
12876  * - allow hexadecimal and octal numbers
12877  * - was restored loses XOR operator
12878  * - remove one goto label, added three ;-)
12879  * - protect $((num num)) as true zero expr (Manuel`s error)
12880  * - always use special isspace(), see comment from bash ;-)
12881  */
12882
12883 #define arith_isspace(arithval) \
12884         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12885
12886 typedef unsigned char operator;
12887
12888 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12889  * precedence, and 3 high bits are an ID unique across operators of that
12890  * precedence. The ID portion is so that multiple operators can have the
12891  * same precedence, ensuring that the leftmost one is evaluated first.
12892  * Consider * and /. */
12893
12894 #define tok_decl(prec,id) (((id)<<5)|(prec))
12895 #define PREC(op) ((op) & 0x1F)
12896
12897 #define TOK_LPAREN tok_decl(0,0)
12898
12899 #define TOK_COMMA tok_decl(1,0)
12900
12901 #define TOK_ASSIGN tok_decl(2,0)
12902 #define TOK_AND_ASSIGN tok_decl(2,1)
12903 #define TOK_OR_ASSIGN tok_decl(2,2)
12904 #define TOK_XOR_ASSIGN tok_decl(2,3)
12905 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12906 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12907 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12908 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12909
12910 #define TOK_MUL_ASSIGN tok_decl(3,0)
12911 #define TOK_DIV_ASSIGN tok_decl(3,1)
12912 #define TOK_REM_ASSIGN tok_decl(3,2)
12913
12914 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12915 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12916
12917 /* conditional is right associativity too */
12918 #define TOK_CONDITIONAL tok_decl(4,0)
12919 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12920
12921 #define TOK_OR tok_decl(5,0)
12922
12923 #define TOK_AND tok_decl(6,0)
12924
12925 #define TOK_BOR tok_decl(7,0)
12926
12927 #define TOK_BXOR tok_decl(8,0)
12928
12929 #define TOK_BAND tok_decl(9,0)
12930
12931 #define TOK_EQ tok_decl(10,0)
12932 #define TOK_NE tok_decl(10,1)
12933
12934 #define TOK_LT tok_decl(11,0)
12935 #define TOK_GT tok_decl(11,1)
12936 #define TOK_GE tok_decl(11,2)
12937 #define TOK_LE tok_decl(11,3)
12938
12939 #define TOK_LSHIFT tok_decl(12,0)
12940 #define TOK_RSHIFT tok_decl(12,1)
12941
12942 #define TOK_ADD tok_decl(13,0)
12943 #define TOK_SUB tok_decl(13,1)
12944
12945 #define TOK_MUL tok_decl(14,0)
12946 #define TOK_DIV tok_decl(14,1)
12947 #define TOK_REM tok_decl(14,2)
12948
12949 /* exponent is right associativity */
12950 #define TOK_EXPONENT tok_decl(15,1)
12951
12952 /* For now unary operators. */
12953 #define UNARYPREC 16
12954 #define TOK_BNOT tok_decl(UNARYPREC,0)
12955 #define TOK_NOT tok_decl(UNARYPREC,1)
12956
12957 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12958 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12959
12960 #define PREC_PRE (UNARYPREC+2)
12961
12962 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12963 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12964
12965 #define PREC_POST (UNARYPREC+3)
12966
12967 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12968 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12969
12970 #define SPEC_PREC (UNARYPREC+4)
12971
12972 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12973 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12974
12975 #define NUMPTR (*numstackptr)
12976
12977 static int
12978 tok_have_assign(operator op)
12979 {
12980         operator prec = PREC(op);
12981
12982         convert_prec_is_assing(prec);
12983         return (prec == PREC(TOK_ASSIGN) ||
12984                         prec == PREC_PRE || prec == PREC_POST);
12985 }
12986
12987 static int
12988 is_right_associativity(operator prec)
12989 {
12990         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12991                 || prec == PREC(TOK_CONDITIONAL));
12992 }
12993
12994 typedef struct {
12995         arith_t val;
12996         arith_t contidional_second_val;
12997         char contidional_second_val_initialized;
12998         char *var;      /* if NULL then is regular number,
12999                            else is variable name */
13000 } v_n_t;
13001
13002 typedef struct chk_var_recursive_looped_t {
13003         const char *var;
13004         struct chk_var_recursive_looped_t *next;
13005 } chk_var_recursive_looped_t;
13006
13007 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13008
13009 static int
13010 arith_lookup_val(v_n_t *t)
13011 {
13012         if (t->var) {
13013                 const char * p = lookupvar(t->var);
13014
13015                 if (p) {
13016                         int errcode;
13017
13018                         /* recursive try as expression */
13019                         chk_var_recursive_looped_t *cur;
13020                         chk_var_recursive_looped_t cur_save;
13021
13022                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13023                                 if (strcmp(cur->var, t->var) == 0) {
13024                                         /* expression recursion loop detected */
13025                                         return -5;
13026                                 }
13027                         }
13028                         /* save current lookuped var name */
13029                         cur = prev_chk_var_recursive;
13030                         cur_save.var = t->var;
13031                         cur_save.next = cur;
13032                         prev_chk_var_recursive = &cur_save;
13033
13034                         t->val = arith (p, &errcode);
13035                         /* restore previous ptr after recursiving */
13036                         prev_chk_var_recursive = cur;
13037                         return errcode;
13038                 }
13039                 /* allow undefined var as 0 */
13040                 t->val = 0;
13041         }
13042         return 0;
13043 }
13044
13045 /* "applying" a token means performing it on the top elements on the integer
13046  * stack. For a unary operator it will only change the top element, but a
13047  * binary operator will pop two arguments and push a result */
13048 static int
13049 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13050 {
13051         v_n_t *numptr_m1;
13052         arith_t numptr_val, rez;
13053         int ret_arith_lookup_val;
13054
13055         /* There is no operator that can work without arguments */
13056         if (NUMPTR == numstack) goto err;
13057         numptr_m1 = NUMPTR - 1;
13058
13059         /* check operand is var with noninteger value */
13060         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13061         if (ret_arith_lookup_val)
13062                 return ret_arith_lookup_val;
13063
13064         rez = numptr_m1->val;
13065         if (op == TOK_UMINUS)
13066                 rez *= -1;
13067         else if (op == TOK_NOT)
13068                 rez = !rez;
13069         else if (op == TOK_BNOT)
13070                 rez = ~rez;
13071         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13072                 rez++;
13073         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13074                 rez--;
13075         else if (op != TOK_UPLUS) {
13076                 /* Binary operators */
13077
13078                 /* check and binary operators need two arguments */
13079                 if (numptr_m1 == numstack) goto err;
13080
13081                 /* ... and they pop one */
13082                 --NUMPTR;
13083                 numptr_val = rez;
13084                 if (op == TOK_CONDITIONAL) {
13085                         if (!numptr_m1->contidional_second_val_initialized) {
13086                                 /* protect $((expr1 ? expr2)) without ": expr" */
13087                                 goto err;
13088                         }
13089                         rez = numptr_m1->contidional_second_val;
13090                 } else if (numptr_m1->contidional_second_val_initialized) {
13091                         /* protect $((expr1 : expr2)) without "expr ? " */
13092                         goto err;
13093                 }
13094                 numptr_m1 = NUMPTR - 1;
13095                 if (op != TOK_ASSIGN) {
13096                         /* check operand is var with noninteger value for not '=' */
13097                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13098                         if (ret_arith_lookup_val)
13099                                 return ret_arith_lookup_val;
13100                 }
13101                 if (op == TOK_CONDITIONAL) {
13102                         numptr_m1->contidional_second_val = rez;
13103                 }
13104                 rez = numptr_m1->val;
13105                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13106                         rez |= numptr_val;
13107                 else if (op == TOK_OR)
13108                         rez = numptr_val || rez;
13109                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13110                         rez &= numptr_val;
13111                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13112                         rez ^= numptr_val;
13113                 else if (op == TOK_AND)
13114                         rez = rez && numptr_val;
13115                 else if (op == TOK_EQ)
13116                         rez = (rez == numptr_val);
13117                 else if (op == TOK_NE)
13118                         rez = (rez != numptr_val);
13119                 else if (op == TOK_GE)
13120                         rez = (rez >= numptr_val);
13121                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13122                         rez >>= numptr_val;
13123                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13124                         rez <<= numptr_val;
13125                 else if (op == TOK_GT)
13126                         rez = (rez > numptr_val);
13127                 else if (op == TOK_LT)
13128                         rez = (rez < numptr_val);
13129                 else if (op == TOK_LE)
13130                         rez = (rez <= numptr_val);
13131                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13132                         rez *= numptr_val;
13133                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13134                         rez += numptr_val;
13135                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13136                         rez -= numptr_val;
13137                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13138                         rez = numptr_val;
13139                 else if (op == TOK_CONDITIONAL_SEP) {
13140                         if (numptr_m1 == numstack) {
13141                                 /* protect $((expr : expr)) without "expr ? " */
13142                                 goto err;
13143                         }
13144                         numptr_m1->contidional_second_val_initialized = op;
13145                         numptr_m1->contidional_second_val = numptr_val;
13146                 } else if (op == TOK_CONDITIONAL) {
13147                         rez = rez ?
13148                                 numptr_val : numptr_m1->contidional_second_val;
13149                 } else if (op == TOK_EXPONENT) {
13150                         if (numptr_val < 0)
13151                                 return -3;      /* exponent less than 0 */
13152                         else {
13153                                 arith_t c = 1;
13154
13155                                 if (numptr_val)
13156                                         while (numptr_val--)
13157                                                 c *= rez;
13158                                 rez = c;
13159                         }
13160                 } else if (numptr_val==0)          /* zero divisor check */
13161                         return -2;
13162                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13163                         rez /= numptr_val;
13164                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13165                         rez %= numptr_val;
13166         }
13167         if (tok_have_assign(op)) {
13168                 char buf[sizeof(arith_t_type)*3 + 2];
13169
13170                 if (numptr_m1->var == NULL) {
13171                         /* Hmm, 1=2 ? */
13172                         goto err;
13173                 }
13174                 /* save to shell variable */
13175 #if ENABLE_ASH_MATH_SUPPORT_64
13176                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13177 #else
13178                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13179 #endif
13180                 setvar(numptr_m1->var, buf, 0);
13181                 /* after saving, make previous value for v++ or v-- */
13182                 if (op == TOK_POST_INC)
13183                         rez--;
13184                 else if (op == TOK_POST_DEC)
13185                         rez++;
13186         }
13187         numptr_m1->val = rez;
13188         /* protect geting var value, is number now */
13189         numptr_m1->var = NULL;
13190         return 0;
13191  err:
13192         return -1;
13193 }
13194
13195 /* longest must be first */
13196 static const char op_tokens[] ALIGN1 = {
13197         '<','<','=',0, TOK_LSHIFT_ASSIGN,
13198         '>','>','=',0, TOK_RSHIFT_ASSIGN,
13199         '<','<',    0, TOK_LSHIFT,
13200         '>','>',    0, TOK_RSHIFT,
13201         '|','|',    0, TOK_OR,
13202         '&','&',    0, TOK_AND,
13203         '!','=',    0, TOK_NE,
13204         '<','=',    0, TOK_LE,
13205         '>','=',    0, TOK_GE,
13206         '=','=',    0, TOK_EQ,
13207         '|','=',    0, TOK_OR_ASSIGN,
13208         '&','=',    0, TOK_AND_ASSIGN,
13209         '*','=',    0, TOK_MUL_ASSIGN,
13210         '/','=',    0, TOK_DIV_ASSIGN,
13211         '%','=',    0, TOK_REM_ASSIGN,
13212         '+','=',    0, TOK_PLUS_ASSIGN,
13213         '-','=',    0, TOK_MINUS_ASSIGN,
13214         '-','-',    0, TOK_POST_DEC,
13215         '^','=',    0, TOK_XOR_ASSIGN,
13216         '+','+',    0, TOK_POST_INC,
13217         '*','*',    0, TOK_EXPONENT,
13218         '!',        0, TOK_NOT,
13219         '<',        0, TOK_LT,
13220         '>',        0, TOK_GT,
13221         '=',        0, TOK_ASSIGN,
13222         '|',        0, TOK_BOR,
13223         '&',        0, TOK_BAND,
13224         '*',        0, TOK_MUL,
13225         '/',        0, TOK_DIV,
13226         '%',        0, TOK_REM,
13227         '+',        0, TOK_ADD,
13228         '-',        0, TOK_SUB,
13229         '^',        0, TOK_BXOR,
13230         /* uniq */
13231         '~',        0, TOK_BNOT,
13232         ',',        0, TOK_COMMA,
13233         '?',        0, TOK_CONDITIONAL,
13234         ':',        0, TOK_CONDITIONAL_SEP,
13235         ')',        0, TOK_RPAREN,
13236         '(',        0, TOK_LPAREN,
13237         0
13238 };
13239 /* ptr to ")" */
13240 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13241
13242 static arith_t
13243 arith(const char *expr, int *perrcode)
13244 {
13245         char arithval; /* Current character under analysis */
13246         operator lasttok, op;
13247         operator prec;
13248         operator *stack, *stackptr;
13249         const char *p = endexpression;
13250         int errcode;
13251         v_n_t *numstack, *numstackptr;
13252         unsigned datasizes = strlen(expr) + 2;
13253
13254         /* Stack of integers */
13255         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13256          * in any given correct or incorrect expression is left as an exercise to
13257          * the reader. */
13258         numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13259         /* Stack of operator tokens */
13260         stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13261
13262         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
13263         *perrcode = errcode = 0;
13264
13265         while (1) {
13266                 arithval = *expr;
13267                 if (arithval == 0) {
13268                         if (p == endexpression) {
13269                                 /* Null expression. */
13270                                 return 0;
13271                         }
13272
13273                         /* This is only reached after all tokens have been extracted from the
13274                          * input stream. If there are still tokens on the operator stack, they
13275                          * are to be applied in order. At the end, there should be a final
13276                          * result on the integer stack */
13277
13278                         if (expr != endexpression + 1) {
13279                                 /* If we haven't done so already, */
13280                                 /* append a closing right paren */
13281                                 expr = endexpression;
13282                                 /* and let the loop process it. */
13283                                 continue;
13284                         }
13285                         /* At this point, we're done with the expression. */
13286                         if (numstackptr != numstack+1) {
13287                                 /* ... but if there isn't, it's bad */
13288  err:
13289                                 *perrcode = -1;
13290                                 return *perrcode;
13291                         }
13292                         if (numstack->var) {
13293                                 /* expression is $((var)) only, lookup now */
13294                                 errcode = arith_lookup_val(numstack);
13295                         }
13296  ret:
13297                         *perrcode = errcode;
13298                         return numstack->val;
13299                 }
13300
13301                 /* Continue processing the expression. */
13302                 if (arith_isspace(arithval)) {
13303                         /* Skip whitespace */
13304                         goto prologue;
13305                 }
13306                 p = endofname(expr);
13307                 if (p != expr) {
13308                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
13309
13310                         numstackptr->var = alloca(var_name_size);
13311                         safe_strncpy(numstackptr->var, expr, var_name_size);
13312                         expr = p;
13313  num:
13314                         numstackptr->contidional_second_val_initialized = 0;
13315                         numstackptr++;
13316                         lasttok = TOK_NUM;
13317                         continue;
13318                 }
13319                 if (isdigit(arithval)) {
13320                         numstackptr->var = NULL;
13321 #if ENABLE_ASH_MATH_SUPPORT_64
13322                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
13323 #else
13324                         numstackptr->val = strtol(expr, (char **) &expr, 0);
13325 #endif
13326                         goto num;
13327                 }
13328                 for (p = op_tokens; ; p++) {
13329                         const char *o;
13330
13331                         if (*p == 0) {
13332                                 /* strange operator not found */
13333                                 goto err;
13334                         }
13335                         for (o = expr; *p && *o == *p; p++)
13336                                 o++;
13337                         if (!*p) {
13338                                 /* found */
13339                                 expr = o - 1;
13340                                 break;
13341                         }
13342                         /* skip tail uncompared token */
13343                         while (*p)
13344                                 p++;
13345                         /* skip zero delim */
13346                         p++;
13347                 }
13348                 op = p[1];
13349
13350                 /* post grammar: a++ reduce to num */
13351                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13352                         lasttok = TOK_NUM;
13353
13354                 /* Plus and minus are binary (not unary) _only_ if the last
13355                  * token was as number, or a right paren (which pretends to be
13356                  * a number, since it evaluates to one). Think about it.
13357                  * It makes sense. */
13358                 if (lasttok != TOK_NUM) {
13359                         switch (op) {
13360                         case TOK_ADD:
13361                                 op = TOK_UPLUS;
13362                                 break;
13363                         case TOK_SUB:
13364                                 op = TOK_UMINUS;
13365                                 break;
13366                         case TOK_POST_INC:
13367                                 op = TOK_PRE_INC;
13368                                 break;
13369                         case TOK_POST_DEC:
13370                                 op = TOK_PRE_DEC;
13371                                 break;
13372                         }
13373                 }
13374                 /* We don't want a unary operator to cause recursive descent on the
13375                  * stack, because there can be many in a row and it could cause an
13376                  * operator to be evaluated before its argument is pushed onto the
13377                  * integer stack. */
13378                 /* But for binary operators, "apply" everything on the operator
13379                  * stack until we find an operator with a lesser priority than the
13380                  * one we have just extracted. */
13381                 /* Left paren is given the lowest priority so it will never be
13382                  * "applied" in this way.
13383                  * if associativity is right and priority eq, applied also skip
13384                  */
13385                 prec = PREC(op);
13386                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13387                         /* not left paren or unary */
13388                         if (lasttok != TOK_NUM) {
13389                                 /* binary op must be preceded by a num */
13390                                 goto err;
13391                         }
13392                         while (stackptr != stack) {
13393                                 if (op == TOK_RPAREN) {
13394                                         /* The algorithm employed here is simple: while we don't
13395                                          * hit an open paren nor the bottom of the stack, pop
13396                                          * tokens and apply them */
13397                                         if (stackptr[-1] == TOK_LPAREN) {
13398                                                 --stackptr;
13399                                                 /* Any operator directly after a */
13400                                                 lasttok = TOK_NUM;
13401                                                 /* close paren should consider itself binary */
13402                                                 goto prologue;
13403                                         }
13404                                 } else {
13405                                         operator prev_prec = PREC(stackptr[-1]);
13406
13407                                         convert_prec_is_assing(prec);
13408                                         convert_prec_is_assing(prev_prec);
13409                                         if (prev_prec < prec)
13410                                                 break;
13411                                         /* check right assoc */
13412                                         if (prev_prec == prec && is_right_associativity(prec))
13413                                                 break;
13414                                 }
13415                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13416                                 if (errcode) goto ret;
13417                         }
13418                         if (op == TOK_RPAREN) {
13419                                 goto err;
13420                         }
13421                 }
13422
13423                 /* Push this operator to the stack and remember it. */
13424                 *stackptr++ = lasttok = op;
13425  prologue:
13426                 ++expr;
13427         } /* while */
13428 }
13429 #endif /* ASH_MATH_SUPPORT */
13430
13431
13432 /* ============ main() and helpers */
13433
13434 /*
13435  * Called to exit the shell.
13436  */
13437 static void exitshell(void) NORETURN;
13438 static void
13439 exitshell(void)
13440 {
13441         struct jmploc loc;
13442         char *p;
13443         int status;
13444
13445         status = exitstatus;
13446         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13447         if (setjmp(loc.loc)) {
13448                 if (exception == EXEXIT)
13449 /* dash bug: it just does _exit(exitstatus) here
13450  * but we have to do setjobctl(0) first!
13451  * (bug is still not fixed in dash-0.5.3 - if you run dash
13452  * under Midnight Commander, on exit from dash MC is backgrounded) */
13453                         status = exitstatus;
13454                 goto out;
13455         }
13456         exception_handler = &loc;
13457         p = trap[0];
13458         if (p) {
13459                 trap[0] = NULL;
13460                 evalstring(p, 0);
13461         }
13462         flush_stdout_stderr();
13463  out:
13464         setjobctl(0);
13465         _exit(status);
13466         /* NOTREACHED */
13467 }
13468
13469 static void
13470 init(void)
13471 {
13472         /* from input.c: */
13473         basepf.next_to_pgetc = basepf.buf = basebuf;
13474
13475         /* from trap.c: */
13476         signal(SIGCHLD, SIG_DFL);
13477
13478         /* from var.c: */
13479         {
13480                 char **envp;
13481                 char ppid[sizeof(int)*3 + 1];
13482                 const char *p;
13483                 struct stat st1, st2;
13484
13485                 initvar();
13486                 for (envp = environ; envp && *envp; envp++) {
13487                         if (strchr(*envp, '=')) {
13488                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13489                         }
13490                 }
13491
13492                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13493                 setvar("PPID", ppid, 0);
13494
13495                 p = lookupvar("PWD");
13496                 if (p)
13497                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13498                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13499                                 p = '\0';
13500                 setpwd(p, 0);
13501         }
13502 }
13503
13504 /*
13505  * Process the shell command line arguments.
13506  */
13507 static void
13508 procargs(char **argv)
13509 {
13510         int i;
13511         const char *xminusc;
13512         char **xargv;
13513
13514         xargv = argv;
13515         arg0 = xargv[0];
13516         /* if (xargv[0]) - mmm, this is always true! */
13517                 xargv++;
13518         for (i = 0; i < NOPTS; i++)
13519                 optlist[i] = 2;
13520         argptr = xargv;
13521         if (options(1)) {
13522                 /* it already printed err message */
13523                 raise_exception(EXERROR);
13524         }
13525         xargv = argptr;
13526         xminusc = minusc;
13527         if (*xargv == NULL) {
13528                 if (xminusc)
13529                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13530                 sflag = 1;
13531         }
13532         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13533                 iflag = 1;
13534         if (mflag == 2)
13535                 mflag = iflag;
13536         for (i = 0; i < NOPTS; i++)
13537                 if (optlist[i] == 2)
13538                         optlist[i] = 0;
13539 #if DEBUG == 2
13540         debug = 1;
13541 #endif
13542         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13543         if (xminusc) {
13544                 minusc = *xargv++;
13545                 if (*xargv)
13546                         goto setarg0;
13547         } else if (!sflag) {
13548                 setinputfile(*xargv, 0);
13549  setarg0:
13550                 arg0 = *xargv++;
13551                 commandname = arg0;
13552         }
13553
13554         shellparam.p = xargv;
13555 #if ENABLE_ASH_GETOPTS
13556         shellparam.optind = 1;
13557         shellparam.optoff = -1;
13558 #endif
13559         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13560         while (*xargv) {
13561                 shellparam.nparam++;
13562                 xargv++;
13563         }
13564         optschanged();
13565 }
13566
13567 /*
13568  * Read /etc/profile or .profile.
13569  */
13570 static void
13571 read_profile(const char *name)
13572 {
13573         int skip;
13574
13575         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13576                 return;
13577         skip = cmdloop(0);
13578         popfile();
13579         if (skip)
13580                 exitshell();
13581 }
13582
13583 /*
13584  * This routine is called when an error or an interrupt occurs in an
13585  * interactive shell and control is returned to the main command loop.
13586  */
13587 static void
13588 reset(void)
13589 {
13590         /* from eval.c: */
13591         evalskip = 0;
13592         loopnest = 0;
13593         /* from input.c: */
13594         g_parsefile->left_in_buffer = 0;
13595         g_parsefile->left_in_line = 0;      /* clear input buffer */
13596         popallfiles();
13597         /* from parser.c: */
13598         tokpushback = 0;
13599         checkkwd = 0;
13600         /* from redir.c: */
13601         clearredir(/*drop:*/ 0);
13602 }
13603
13604 #if PROFILE
13605 static short profile_buf[16384];
13606 extern int etext();
13607 #endif
13608
13609 /*
13610  * Main routine.  We initialize things, parse the arguments, execute
13611  * profiles if we're a login shell, and then call cmdloop to execute
13612  * commands.  The setjmp call sets up the location to jump to when an
13613  * exception occurs.  When an exception occurs the variable "state"
13614  * is used to figure out how far we had gotten.
13615  */
13616 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13617 int ash_main(int argc UNUSED_PARAM, char **argv)
13618 {
13619         char *shinit;
13620         volatile int state;
13621         struct jmploc jmploc;
13622         struct stackmark smark;
13623
13624         /* Initialize global data */
13625         INIT_G_misc();
13626         INIT_G_memstack();
13627         INIT_G_var();
13628 #if ENABLE_ASH_ALIAS
13629         INIT_G_alias();
13630 #endif
13631         INIT_G_cmdtable();
13632
13633 #if PROFILE
13634         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13635 #endif
13636
13637 #if ENABLE_FEATURE_EDITING
13638         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13639 #endif
13640         state = 0;
13641         if (setjmp(jmploc.loc)) {
13642                 int e;
13643                 int s;
13644
13645                 reset();
13646
13647                 e = exception;
13648                 if (e == EXERROR)
13649                         exitstatus = 2;
13650                 s = state;
13651                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13652                         exitshell();
13653
13654                 if (e == EXINT) {
13655                         outcslow('\n', stderr);
13656                 }
13657                 popstackmark(&smark);
13658                 FORCE_INT_ON; /* enable interrupts */
13659                 if (s == 1)
13660                         goto state1;
13661                 if (s == 2)
13662                         goto state2;
13663                 if (s == 3)
13664                         goto state3;
13665                 goto state4;
13666         }
13667         exception_handler = &jmploc;
13668 #if DEBUG
13669         opentrace();
13670         trace_puts("Shell args: ");
13671         trace_puts_args(argv);
13672 #endif
13673         rootpid = getpid();
13674
13675 #if ENABLE_ASH_RANDOM_SUPPORT
13676         /* Can use monotonic_ns() for better randomness but for now it is
13677          * not used anywhere else in busybox... so avoid bloat */
13678         random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13679 #endif
13680         init();
13681         setstackmark(&smark);
13682         procargs(argv);
13683
13684 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13685         if (iflag) {
13686                 const char *hp = lookupvar("HISTFILE");
13687
13688                 if (hp == NULL) {
13689                         hp = lookupvar("HOME");
13690                         if (hp != NULL) {
13691                                 char *defhp = concat_path_file(hp, ".ash_history");
13692                                 setvar("HISTFILE", defhp, 0);
13693                                 free(defhp);
13694                         }
13695                 }
13696         }
13697 #endif
13698         if (argv[0] && argv[0][0] == '-')
13699                 isloginsh = 1;
13700         if (isloginsh) {
13701                 state = 1;
13702                 read_profile("/etc/profile");
13703  state1:
13704                 state = 2;
13705                 read_profile(".profile");
13706         }
13707  state2:
13708         state = 3;
13709         if (
13710 #ifndef linux
13711          getuid() == geteuid() && getgid() == getegid() &&
13712 #endif
13713          iflag
13714         ) {
13715                 shinit = lookupvar("ENV");
13716                 if (shinit != NULL && *shinit != '\0') {
13717                         read_profile(shinit);
13718                 }
13719         }
13720  state3:
13721         state = 4;
13722         if (minusc)
13723                 evalstring(minusc, 0);
13724
13725         if (sflag || minusc == NULL) {
13726 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13727                 if (iflag) {
13728                         const char *hp = lookupvar("HISTFILE");
13729
13730                         if (hp != NULL)
13731                                 line_input_state->hist_file = hp;
13732                 }
13733 #endif
13734  state4: /* XXX ??? - why isn't this before the "if" statement */
13735                 cmdloop(1);
13736         }
13737 #if PROFILE
13738         monitor(0);
13739 #endif
13740 #ifdef GPROF
13741         {
13742                 extern void _mcleanup(void);
13743                 _mcleanup();
13744         }
13745 #endif
13746         exitshell();
13747         /* NOTREACHED */
13748 }
13749
13750 #if DEBUG
13751 const char *applet_name = "debug stuff usage";
13752 int main(int argc, char **argv)
13753 {
13754         return ash_main(argc, argv);
13755 }
13756 #endif
13757
13758
13759 /*-
13760  * Copyright (c) 1989, 1991, 1993, 1994
13761  *      The Regents of the University of California.  All rights reserved.
13762  *
13763  * This code is derived from software contributed to Berkeley by
13764  * Kenneth Almquist.
13765  *
13766  * Redistribution and use in source and binary forms, with or without
13767  * modification, are permitted provided that the following conditions
13768  * are met:
13769  * 1. Redistributions of source code must retain the above copyright
13770  *    notice, this list of conditions and the following disclaimer.
13771  * 2. Redistributions in binary form must reproduce the above copyright
13772  *    notice, this list of conditions and the following disclaimer in the
13773  *    documentation and/or other materials provided with the distribution.
13774  * 3. Neither the name of the University nor the names of its contributors
13775  *    may be used to endorse or promote products derived from this software
13776  *    without specific prior written permission.
13777  *
13778  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13779  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13780  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13781  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13782  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13783  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13784  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13785  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13786  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13787  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13788  * SUCH DAMAGE.
13789  */