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