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