f93d73735e000e90c1991204d01eba9b42580bbe
[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 NOMMU machine"
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 says: "char" declaration may be signed or unsigned by 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_type; /* 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_type    (G_misc.exception_type   )
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_type = 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
389         if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
390                 if (!suppressint) {
391                         pendingsig = 0;
392                         raise_interrupt(); /* does not return */
393                 }
394                 intpending = 1;
395         } else {
396                 pendingsig = signo;
397         }
398 }
399
400
401 /* ============ Stdout/stderr output */
402
403 static void
404 outstr(const char *p, FILE *file)
405 {
406         INT_OFF;
407         fputs(p, file);
408         INT_ON;
409 }
410
411 static void
412 flush_stdout_stderr(void)
413 {
414         INT_OFF;
415         fflush(stdout);
416         fflush(stderr);
417         INT_ON;
418 }
419
420 static void
421 flush_stderr(void)
422 {
423         INT_OFF;
424         fflush(stderr);
425         INT_ON;
426 }
427
428 static void
429 outcslow(int c, FILE *dest)
430 {
431         INT_OFF;
432         putc(c, dest);
433         fflush(dest);
434         INT_ON;
435 }
436
437 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
438 static int
439 out1fmt(const char *fmt, ...)
440 {
441         va_list ap;
442         int r;
443
444         INT_OFF;
445         va_start(ap, fmt);
446         r = vprintf(fmt, ap);
447         va_end(ap);
448         INT_ON;
449         return r;
450 }
451
452 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
453 static int
454 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
455 {
456         va_list ap;
457         int ret;
458
459         va_start(ap, fmt);
460         INT_OFF;
461         ret = vsnprintf(outbuf, length, fmt, ap);
462         va_end(ap);
463         INT_ON;
464         return ret;
465 }
466
467 static void
468 out1str(const char *p)
469 {
470         outstr(p, stdout);
471 }
472
473 static void
474 out2str(const char *p)
475 {
476         outstr(p, stderr);
477         flush_stderr();
478 }
479
480
481 /* ============ Parser structures */
482
483 /* control characters in argument strings */
484 #define CTLESC '\201'           /* escape next character */
485 #define CTLVAR '\202'           /* variable defn */
486 #define CTLENDVAR '\203'
487 #define CTLBACKQ '\204'
488 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
489 /*      CTLBACKQ | CTLQUOTE == '\205' */
490 #define CTLARI  '\206'          /* arithmetic expression */
491 #define CTLENDARI '\207'
492 #define CTLQUOTEMARK '\210'
493
494 /* variable substitution byte (follows CTLVAR) */
495 #define VSTYPE  0x0f            /* type of variable substitution */
496 #define VSNUL   0x10            /* colon--treat the empty string as unset */
497 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
498
499 /* values of VSTYPE field */
500 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
501 #define VSMINUS         0x2     /* ${var-text} */
502 #define VSPLUS          0x3     /* ${var+text} */
503 #define VSQUESTION      0x4     /* ${var?message} */
504 #define VSASSIGN        0x5     /* ${var=text} */
505 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
506 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
507 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
508 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
509 #define VSLENGTH        0xa     /* ${#var} */
510 #if ENABLE_ASH_BASH_COMPAT
511 #define VSSUBSTR        0xc     /* ${var:position:length} */
512 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
513 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
514 #endif
515
516 static const char dolatstr[] ALIGN1 = {
517         CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
518 };
519
520 #define NCMD      0
521 #define NPIPE     1
522 #define NREDIR    2
523 #define NBACKGND  3
524 #define NSUBSHELL 4
525 #define NAND      5
526 #define NOR       6
527 #define NSEMI     7
528 #define NIF       8
529 #define NWHILE    9
530 #define NUNTIL   10
531 #define NFOR     11
532 #define NCASE    12
533 #define NCLIST   13
534 #define NDEFUN   14
535 #define NARG     15
536 #define NTO      16
537 #if ENABLE_ASH_BASH_COMPAT
538 #define NTO2     17
539 #endif
540 #define NCLOBBER 18
541 #define NFROM    19
542 #define NFROMTO  20
543 #define NAPPEND  21
544 #define NTOFD    22
545 #define NFROMFD  23
546 #define NHERE    24
547 #define NXHERE   25
548 #define NNOT     26
549 #define N_NUMBER 27
550
551 union node;
552
553 struct ncmd {
554         smallint type; /* Nxxxx */
555         union node *assign;
556         union node *args;
557         union node *redirect;
558 };
559
560 struct npipe {
561         smallint type;
562         smallint pipe_backgnd;
563         struct nodelist *cmdlist;
564 };
565
566 struct nredir {
567         smallint type;
568         union node *n;
569         union node *redirect;
570 };
571
572 struct nbinary {
573         smallint type;
574         union node *ch1;
575         union node *ch2;
576 };
577
578 struct nif {
579         smallint type;
580         union node *test;
581         union node *ifpart;
582         union node *elsepart;
583 };
584
585 struct nfor {
586         smallint type;
587         union node *args;
588         union node *body;
589         char *var;
590 };
591
592 struct ncase {
593         smallint type;
594         union node *expr;
595         union node *cases;
596 };
597
598 struct nclist {
599         smallint type;
600         union node *next;
601         union node *pattern;
602         union node *body;
603 };
604
605 struct narg {
606         smallint type;
607         union node *next;
608         char *text;
609         struct nodelist *backquote;
610 };
611
612 /* nfile and ndup layout must match!
613  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
614  * that it is actually NTO2 (>&file), and change its type.
615  */
616 struct nfile {
617         smallint type;
618         union node *next;
619         int fd;
620         int _unused_dupfd;
621         union node *fname;
622         char *expfname;
623 };
624
625 struct ndup {
626         smallint type;
627         union node *next;
628         int fd;
629         int dupfd;
630         union node *vname;
631         char *_unused_expfname;
632 };
633
634 struct nhere {
635         smallint type;
636         union node *next;
637         int fd;
638         union node *doc;
639 };
640
641 struct nnot {
642         smallint type;
643         union node *com;
644 };
645
646 union node {
647         smallint type;
648         struct ncmd ncmd;
649         struct npipe npipe;
650         struct nredir nredir;
651         struct nbinary nbinary;
652         struct nif nif;
653         struct nfor nfor;
654         struct ncase ncase;
655         struct nclist nclist;
656         struct narg narg;
657         struct nfile nfile;
658         struct ndup ndup;
659         struct nhere nhere;
660         struct nnot nnot;
661 };
662
663 struct nodelist {
664         struct nodelist *next;
665         union node *n;
666 };
667
668 struct funcnode {
669         int count;
670         union node n;
671 };
672
673 /*
674  * Free a parse tree.
675  */
676 static void
677 freefunc(struct funcnode *f)
678 {
679         if (f && --f->count < 0)
680                 free(f);
681 }
682
683
684 /* ============ Debugging output */
685
686 #if DEBUG
687
688 static FILE *tracefile;
689
690 static void
691 trace_printf(const char *fmt, ...)
692 {
693         va_list va;
694
695         if (debug != 1)
696                 return;
697         va_start(va, fmt);
698         vfprintf(tracefile, fmt, va);
699         va_end(va);
700 }
701
702 static void
703 trace_vprintf(const char *fmt, va_list va)
704 {
705         if (debug != 1)
706                 return;
707         vfprintf(tracefile, fmt, va);
708 }
709
710 static void
711 trace_puts(const char *s)
712 {
713         if (debug != 1)
714                 return;
715         fputs(s, tracefile);
716 }
717
718 static void
719 trace_puts_quoted(char *s)
720 {
721         char *p;
722         char c;
723
724         if (debug != 1)
725                 return;
726         putc('"', tracefile);
727         for (p = s; *p; p++) {
728                 switch (*p) {
729                 case '\n':  c = 'n';  goto backslash;
730                 case '\t':  c = 't';  goto backslash;
731                 case '\r':  c = 'r';  goto backslash;
732                 case '"':  c = '"';  goto backslash;
733                 case '\\':  c = '\\';  goto backslash;
734                 case CTLESC:  c = 'e';  goto backslash;
735                 case CTLVAR:  c = 'v';  goto backslash;
736                 case CTLVAR+CTLQUOTE:  c = 'V'; goto backslash;
737                 case CTLBACKQ:  c = 'q';  goto backslash;
738                 case CTLBACKQ+CTLQUOTE:  c = 'Q'; goto backslash;
739  backslash:
740                         putc('\\', tracefile);
741                         putc(c, tracefile);
742                         break;
743                 default:
744                         if (*p >= ' ' && *p <= '~')
745                                 putc(*p, tracefile);
746                         else {
747                                 putc('\\', tracefile);
748                                 putc(*p >> 6 & 03, tracefile);
749                                 putc(*p >> 3 & 07, tracefile);
750                                 putc(*p & 07, tracefile);
751                         }
752                         break;
753                 }
754         }
755         putc('"', tracefile);
756 }
757
758 static void
759 trace_puts_args(char **ap)
760 {
761         if (debug != 1)
762                 return;
763         if (!*ap)
764                 return;
765         while (1) {
766                 trace_puts_quoted(*ap);
767                 if (!*++ap) {
768                         putc('\n', tracefile);
769                         break;
770                 }
771                 putc(' ', tracefile);
772         }
773 }
774
775 static void
776 opentrace(void)
777 {
778         char s[100];
779 #ifdef O_APPEND
780         int flags;
781 #endif
782
783         if (debug != 1) {
784                 if (tracefile)
785                         fflush(tracefile);
786                 /* leave open because libedit might be using it */
787                 return;
788         }
789         strcpy(s, "./trace");
790         if (tracefile) {
791                 if (!freopen(s, "a", tracefile)) {
792                         fprintf(stderr, "Can't re-open %s\n", s);
793                         debug = 0;
794                         return;
795                 }
796         } else {
797                 tracefile = fopen(s, "a");
798                 if (tracefile == NULL) {
799                         fprintf(stderr, "Can't open %s\n", s);
800                         debug = 0;
801                         return;
802                 }
803         }
804 #ifdef O_APPEND
805         flags = fcntl(fileno(tracefile), F_GETFL);
806         if (flags >= 0)
807                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
808 #endif
809         setlinebuf(tracefile);
810         fputs("\nTracing started.\n", tracefile);
811 }
812
813 static void
814 indent(int amount, char *pfx, FILE *fp)
815 {
816         int i;
817
818         for (i = 0; i < amount; i++) {
819                 if (pfx && i == amount - 1)
820                         fputs(pfx, fp);
821                 putc('\t', fp);
822         }
823 }
824
825 /* little circular references here... */
826 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
827
828 static void
829 sharg(union node *arg, FILE *fp)
830 {
831         char *p;
832         struct nodelist *bqlist;
833         int subtype;
834
835         if (arg->type != NARG) {
836                 out1fmt("<node type %d>\n", arg->type);
837                 abort();
838         }
839         bqlist = arg->narg.backquote;
840         for (p = arg->narg.text; *p; p++) {
841                 switch (*p) {
842                 case CTLESC:
843                         putc(*++p, fp);
844                         break;
845                 case CTLVAR:
846                         putc('$', fp);
847                         putc('{', fp);
848                         subtype = *++p;
849                         if (subtype == VSLENGTH)
850                                 putc('#', fp);
851
852                         while (*p != '=')
853                                 putc(*p++, fp);
854
855                         if (subtype & VSNUL)
856                                 putc(':', fp);
857
858                         switch (subtype & VSTYPE) {
859                         case VSNORMAL:
860                                 putc('}', fp);
861                                 break;
862                         case VSMINUS:
863                                 putc('-', fp);
864                                 break;
865                         case VSPLUS:
866                                 putc('+', fp);
867                                 break;
868                         case VSQUESTION:
869                                 putc('?', fp);
870                                 break;
871                         case VSASSIGN:
872                                 putc('=', fp);
873                                 break;
874                         case VSTRIMLEFT:
875                                 putc('#', fp);
876                                 break;
877                         case VSTRIMLEFTMAX:
878                                 putc('#', fp);
879                                 putc('#', fp);
880                                 break;
881                         case VSTRIMRIGHT:
882                                 putc('%', fp);
883                                 break;
884                         case VSTRIMRIGHTMAX:
885                                 putc('%', fp);
886                                 putc('%', fp);
887                                 break;
888                         case VSLENGTH:
889                                 break;
890                         default:
891                                 out1fmt("<subtype %d>", subtype);
892                         }
893                         break;
894                 case CTLENDVAR:
895                         putc('}', fp);
896                         break;
897                 case CTLBACKQ:
898                 case CTLBACKQ|CTLQUOTE:
899                         putc('$', fp);
900                         putc('(', fp);
901                         shtree(bqlist->n, -1, NULL, fp);
902                         putc(')', fp);
903                         break;
904                 default:
905                         putc(*p, fp);
906                         break;
907                 }
908         }
909 }
910
911 static void
912 shcmd(union node *cmd, FILE *fp)
913 {
914         union node *np;
915         int first;
916         const char *s;
917         int dftfd;
918
919         first = 1;
920         for (np = cmd->ncmd.args; np; np = np->narg.next) {
921                 if (!first)
922                         putc(' ', fp);
923                 sharg(np, fp);
924                 first = 0;
925         }
926         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
927                 if (!first)
928                         putc(' ', fp);
929                 dftfd = 0;
930                 switch (np->nfile.type) {
931                 case NTO:      s = ">>"+1; dftfd = 1; break;
932                 case NCLOBBER: s = ">|"; dftfd = 1; break;
933                 case NAPPEND:  s = ">>"; dftfd = 1; break;
934 #if ENABLE_ASH_BASH_COMPAT
935                 case NTO2:
936 #endif
937                 case NTOFD:    s = ">&"; dftfd = 1; break;
938                 case NFROM:    s = "<"; break;
939                 case NFROMFD:  s = "<&"; break;
940                 case NFROMTO:  s = "<>"; break;
941                 default:       s = "*error*"; break;
942                 }
943                 if (np->nfile.fd != dftfd)
944                         fprintf(fp, "%d", np->nfile.fd);
945                 fputs(s, fp);
946                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
947                         fprintf(fp, "%d", np->ndup.dupfd);
948                 } else {
949                         sharg(np->nfile.fname, fp);
950                 }
951                 first = 0;
952         }
953 }
954
955 static void
956 shtree(union node *n, int ind, char *pfx, FILE *fp)
957 {
958         struct nodelist *lp;
959         const char *s;
960
961         if (n == NULL)
962                 return;
963
964         indent(ind, pfx, fp);
965         switch (n->type) {
966         case NSEMI:
967                 s = "; ";
968                 goto binop;
969         case NAND:
970                 s = " && ";
971                 goto binop;
972         case NOR:
973                 s = " || ";
974  binop:
975                 shtree(n->nbinary.ch1, ind, NULL, fp);
976                 /* if (ind < 0) */
977                         fputs(s, fp);
978                 shtree(n->nbinary.ch2, ind, NULL, fp);
979                 break;
980         case NCMD:
981                 shcmd(n, fp);
982                 if (ind >= 0)
983                         putc('\n', fp);
984                 break;
985         case NPIPE:
986                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
987                         shcmd(lp->n, fp);
988                         if (lp->next)
989                                 fputs(" | ", fp);
990                 }
991                 if (n->npipe.pipe_backgnd)
992                         fputs(" &", fp);
993                 if (ind >= 0)
994                         putc('\n', fp);
995                 break;
996         default:
997                 fprintf(fp, "<node type %d>", n->type);
998                 if (ind >= 0)
999                         putc('\n', fp);
1000                 break;
1001         }
1002 }
1003
1004 static void
1005 showtree(union node *n)
1006 {
1007         trace_puts("showtree called\n");
1008         shtree(n, 1, NULL, stdout);
1009 }
1010
1011 #define TRACE(param)    trace_printf param
1012 #define TRACEV(param)   trace_vprintf param
1013
1014 #else
1015
1016 #define TRACE(param)
1017 #define TRACEV(param)
1018
1019 #endif /* DEBUG */
1020
1021
1022 /* ============ Parser data */
1023
1024 /*
1025  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1026  */
1027 struct strlist {
1028         struct strlist *next;
1029         char *text;
1030 };
1031
1032 struct alias;
1033
1034 struct strpush {
1035         struct strpush *prev;   /* preceding string on stack */
1036         char *prev_string;
1037         int prev_left_in_line;
1038 #if ENABLE_ASH_ALIAS
1039         struct alias *ap;       /* if push was associated with an alias */
1040 #endif
1041         char *string;           /* remember the string since it may change */
1042 };
1043
1044 struct parsefile {
1045         struct parsefile *prev; /* preceding file on stack */
1046         int linno;              /* current line */
1047         int fd;                 /* file descriptor (or -1 if string) */
1048         int left_in_line;       /* number of chars left in this line */
1049         int left_in_buffer;     /* number of chars left in this buffer past the line */
1050         char *next_to_pgetc;    /* next char in buffer */
1051         char *buf;              /* input buffer */
1052         struct strpush *strpush; /* for pushing strings at this level */
1053         struct strpush basestrpush; /* so pushing one is fast */
1054 };
1055
1056 static struct parsefile basepf;        /* top level input file */
1057 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1058 static int startlinno;                 /* line # where last token started */
1059 static char *commandname;              /* currently executing command */
1060 static struct strlist *cmdenviron;     /* environment for builtin command */
1061 static uint8_t exitstatus;             /* exit status of last command */
1062
1063
1064 /* ============ Message printing */
1065
1066 static void
1067 ash_vmsg(const char *msg, va_list ap)
1068 {
1069         fprintf(stderr, "%s: ", arg0);
1070         if (commandname) {
1071                 if (strcmp(arg0, commandname))
1072                         fprintf(stderr, "%s: ", commandname);
1073                 if (!iflag || g_parsefile->fd)
1074                         fprintf(stderr, "line %d: ", startlinno);
1075         }
1076         vfprintf(stderr, msg, ap);
1077         outcslow('\n', stderr);
1078 }
1079
1080 /*
1081  * Exverror is called to raise the error exception.  If the second argument
1082  * is not NULL then error prints an error message using printf style
1083  * formatting.  It then raises the error exception.
1084  */
1085 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1086 static void
1087 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1088 {
1089 #if DEBUG
1090         if (msg) {
1091                 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1092                 TRACEV((msg, ap));
1093                 TRACE(("\") pid=%d\n", getpid()));
1094         } else
1095                 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1096         if (msg)
1097 #endif
1098                 ash_vmsg(msg, ap);
1099
1100         flush_stdout_stderr();
1101         raise_exception(cond);
1102         /* NOTREACHED */
1103 }
1104
1105 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1106 static void
1107 ash_msg_and_raise_error(const char *msg, ...)
1108 {
1109         va_list ap;
1110
1111         va_start(ap, msg);
1112         ash_vmsg_and_raise(EXERROR, msg, ap);
1113         /* NOTREACHED */
1114         va_end(ap);
1115 }
1116
1117 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1118 static void
1119 ash_msg_and_raise(int cond, const char *msg, ...)
1120 {
1121         va_list ap;
1122
1123         va_start(ap, msg);
1124         ash_vmsg_and_raise(cond, msg, ap);
1125         /* NOTREACHED */
1126         va_end(ap);
1127 }
1128
1129 /*
1130  * error/warning routines for external builtins
1131  */
1132 static void
1133 ash_msg(const char *fmt, ...)
1134 {
1135         va_list ap;
1136
1137         va_start(ap, fmt);
1138         ash_vmsg(fmt, ap);
1139         va_end(ap);
1140 }
1141
1142 /*
1143  * Return a string describing an error.  The returned string may be a
1144  * pointer to a static buffer that will be overwritten on the next call.
1145  * Action describes the operation that got the error.
1146  */
1147 static const char *
1148 errmsg(int e, const char *em)
1149 {
1150         if (e == ENOENT || e == ENOTDIR) {
1151                 return em;
1152         }
1153         return strerror(e);
1154 }
1155
1156
1157 /* ============ Memory allocation */
1158
1159 /*
1160  * It appears that grabstackstr() will barf with such alignments
1161  * because stalloc() will return a string allocated in a new stackblock.
1162  */
1163 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1164 enum {
1165         /* Most machines require the value returned from malloc to be aligned
1166          * in some way.  The following macro will get this right
1167          * on many machines.  */
1168         SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1169         /* Minimum size of a block */
1170         MINSIZE = SHELL_ALIGN(504),
1171 };
1172
1173 struct stack_block {
1174         struct stack_block *prev;
1175         char space[MINSIZE];
1176 };
1177
1178 struct stackmark {
1179         struct stack_block *stackp;
1180         char *stacknxt;
1181         size_t stacknleft;
1182         struct stackmark *marknext;
1183 };
1184
1185
1186 struct globals_memstack {
1187         struct stack_block *g_stackp; // = &stackbase;
1188         struct stackmark *markp;
1189         char *g_stacknxt; // = stackbase.space;
1190         char *sstrend; // = stackbase.space + MINSIZE;
1191         size_t g_stacknleft; // = MINSIZE;
1192         int    herefd; // = -1;
1193         struct stack_block stackbase;
1194 };
1195 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1196 #define G_memstack (*ash_ptr_to_globals_memstack)
1197 #define g_stackp     (G_memstack.g_stackp    )
1198 #define markp        (G_memstack.markp       )
1199 #define g_stacknxt   (G_memstack.g_stacknxt  )
1200 #define sstrend      (G_memstack.sstrend     )
1201 #define g_stacknleft (G_memstack.g_stacknleft)
1202 #define herefd       (G_memstack.herefd      )
1203 #define stackbase    (G_memstack.stackbase   )
1204 #define INIT_G_memstack() do { \
1205         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1206         barrier(); \
1207         g_stackp = &stackbase; \
1208         g_stacknxt = stackbase.space; \
1209         g_stacknleft = MINSIZE; \
1210         sstrend = stackbase.space + MINSIZE; \
1211         herefd = -1; \
1212 } while (0)
1213
1214 #define stackblock()     ((void *)g_stacknxt)
1215 #define stackblocksize() g_stacknleft
1216
1217
1218 static void *
1219 ckrealloc(void * p, size_t nbytes)
1220 {
1221         p = realloc(p, nbytes);
1222         if (!p)
1223                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1224         return p;
1225 }
1226
1227 static void *
1228 ckmalloc(size_t nbytes)
1229 {
1230         return ckrealloc(NULL, nbytes);
1231 }
1232
1233 static void *
1234 ckzalloc(size_t nbytes)
1235 {
1236         return memset(ckmalloc(nbytes), 0, nbytes);
1237 }
1238
1239 /*
1240  * Make a copy of a string in safe storage.
1241  */
1242 static char *
1243 ckstrdup(const char *s)
1244 {
1245         char *p = strdup(s);
1246         if (!p)
1247                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1248         return p;
1249 }
1250
1251 /*
1252  * Parse trees for commands are allocated in lifo order, so we use a stack
1253  * to make this more efficient, and also to avoid all sorts of exception
1254  * handling code to handle interrupts in the middle of a parse.
1255  *
1256  * The size 504 was chosen because the Ultrix malloc handles that size
1257  * well.
1258  */
1259 static void *
1260 stalloc(size_t nbytes)
1261 {
1262         char *p;
1263         size_t aligned;
1264
1265         aligned = SHELL_ALIGN(nbytes);
1266         if (aligned > g_stacknleft) {
1267                 size_t len;
1268                 size_t blocksize;
1269                 struct stack_block *sp;
1270
1271                 blocksize = aligned;
1272                 if (blocksize < MINSIZE)
1273                         blocksize = MINSIZE;
1274                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1275                 if (len < blocksize)
1276                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1277                 INT_OFF;
1278                 sp = ckmalloc(len);
1279                 sp->prev = g_stackp;
1280                 g_stacknxt = sp->space;
1281                 g_stacknleft = blocksize;
1282                 sstrend = g_stacknxt + blocksize;
1283                 g_stackp = sp;
1284                 INT_ON;
1285         }
1286         p = g_stacknxt;
1287         g_stacknxt += aligned;
1288         g_stacknleft -= aligned;
1289         return p;
1290 }
1291
1292 static void *
1293 stzalloc(size_t nbytes)
1294 {
1295         return memset(stalloc(nbytes), 0, nbytes);
1296 }
1297
1298 static void
1299 stunalloc(void *p)
1300 {
1301 #if DEBUG
1302         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1303                 write(STDERR_FILENO, "stunalloc\n", 10);
1304                 abort();
1305         }
1306 #endif
1307         g_stacknleft += g_stacknxt - (char *)p;
1308         g_stacknxt = p;
1309 }
1310
1311 /*
1312  * Like strdup but works with the ash stack.
1313  */
1314 static char *
1315 ststrdup(const char *p)
1316 {
1317         size_t len = strlen(p) + 1;
1318         return memcpy(stalloc(len), p, len);
1319 }
1320
1321 static void
1322 setstackmark(struct stackmark *mark)
1323 {
1324         mark->stackp = g_stackp;
1325         mark->stacknxt = g_stacknxt;
1326         mark->stacknleft = g_stacknleft;
1327         mark->marknext = markp;
1328         markp = mark;
1329 }
1330
1331 static void
1332 popstackmark(struct stackmark *mark)
1333 {
1334         struct stack_block *sp;
1335
1336         if (!mark->stackp)
1337                 return;
1338
1339         INT_OFF;
1340         markp = mark->marknext;
1341         while (g_stackp != mark->stackp) {
1342                 sp = g_stackp;
1343                 g_stackp = sp->prev;
1344                 free(sp);
1345         }
1346         g_stacknxt = mark->stacknxt;
1347         g_stacknleft = mark->stacknleft;
1348         sstrend = mark->stacknxt + mark->stacknleft;
1349         INT_ON;
1350 }
1351
1352 /*
1353  * When the parser reads in a string, it wants to stick the string on the
1354  * stack and only adjust the stack pointer when it knows how big the
1355  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1356  * of space on top of the stack and stackblocklen returns the length of
1357  * this block.  Growstackblock will grow this space by at least one byte,
1358  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1359  * part of the block that has been used.
1360  */
1361 static void
1362 growstackblock(void)
1363 {
1364         size_t newlen;
1365
1366         newlen = g_stacknleft * 2;
1367         if (newlen < g_stacknleft)
1368                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1369         if (newlen < 128)
1370                 newlen += 128;
1371
1372         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1373                 struct stack_block *oldstackp;
1374                 struct stackmark *xmark;
1375                 struct stack_block *sp;
1376                 struct stack_block *prevstackp;
1377                 size_t grosslen;
1378
1379                 INT_OFF;
1380                 oldstackp = g_stackp;
1381                 sp = g_stackp;
1382                 prevstackp = sp->prev;
1383                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1384                 sp = ckrealloc(sp, grosslen);
1385                 sp->prev = prevstackp;
1386                 g_stackp = sp;
1387                 g_stacknxt = sp->space;
1388                 g_stacknleft = newlen;
1389                 sstrend = sp->space + newlen;
1390
1391                 /*
1392                  * Stack marks pointing to the start of the old block
1393                  * must be relocated to point to the new block
1394                  */
1395                 xmark = markp;
1396                 while (xmark != NULL && xmark->stackp == oldstackp) {
1397                         xmark->stackp = g_stackp;
1398                         xmark->stacknxt = g_stacknxt;
1399                         xmark->stacknleft = g_stacknleft;
1400                         xmark = xmark->marknext;
1401                 }
1402                 INT_ON;
1403         } else {
1404                 char *oldspace = g_stacknxt;
1405                 size_t oldlen = g_stacknleft;
1406                 char *p = stalloc(newlen);
1407
1408                 /* free the space we just allocated */
1409                 g_stacknxt = memcpy(p, oldspace, oldlen);
1410                 g_stacknleft += newlen;
1411         }
1412 }
1413
1414 static void
1415 grabstackblock(size_t len)
1416 {
1417         len = SHELL_ALIGN(len);
1418         g_stacknxt += len;
1419         g_stacknleft -= len;
1420 }
1421
1422 /*
1423  * The following routines are somewhat easier to use than the above.
1424  * The user declares a variable of type STACKSTR, which may be declared
1425  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1426  * the user uses the macro STPUTC to add characters to the string.  In
1427  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1428  * grown as necessary.  When the user is done, she can just leave the
1429  * string there and refer to it using stackblock().  Or she can allocate
1430  * the space for it using grabstackstr().  If it is necessary to allow
1431  * someone else to use the stack temporarily and then continue to grow
1432  * the string, the user should use grabstack to allocate the space, and
1433  * then call ungrabstr(p) to return to the previous mode of operation.
1434  *
1435  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1436  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1437  * is space for at least one character.
1438  */
1439 static void *
1440 growstackstr(void)
1441 {
1442         size_t len = stackblocksize();
1443         if (herefd >= 0 && len >= 1024) {
1444                 full_write(herefd, stackblock(), len);
1445                 return stackblock();
1446         }
1447         growstackblock();
1448         return (char *)stackblock() + len;
1449 }
1450
1451 /*
1452  * Called from CHECKSTRSPACE.
1453  */
1454 static char *
1455 makestrspace(size_t newlen, char *p)
1456 {
1457         size_t len = p - g_stacknxt;
1458         size_t size = stackblocksize();
1459
1460         for (;;) {
1461                 size_t nleft;
1462
1463                 size = stackblocksize();
1464                 nleft = size - len;
1465                 if (nleft >= newlen)
1466                         break;
1467                 growstackblock();
1468         }
1469         return (char *)stackblock() + len;
1470 }
1471
1472 static char *
1473 stack_nputstr(const char *s, size_t n, char *p)
1474 {
1475         p = makestrspace(n, p);
1476         p = (char *)memcpy(p, s, n) + n;
1477         return p;
1478 }
1479
1480 static char *
1481 stack_putstr(const char *s, char *p)
1482 {
1483         return stack_nputstr(s, strlen(s), p);
1484 }
1485
1486 static char *
1487 _STPUTC(int c, char *p)
1488 {
1489         if (p == sstrend)
1490                 p = growstackstr();
1491         *p++ = c;
1492         return p;
1493 }
1494
1495 #define STARTSTACKSTR(p)        ((p) = stackblock())
1496 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1497 #define CHECKSTRSPACE(n, p) do { \
1498         char *q = (p); \
1499         size_t l = (n); \
1500         size_t m = sstrend - q; \
1501         if (l > m) \
1502                 (p) = makestrspace(l, q); \
1503 } while (0)
1504 #define USTPUTC(c, p)           (*(p)++ = (c))
1505 #define STACKSTRNUL(p) do { \
1506         if ((p) == sstrend) \
1507                 (p) = growstackstr(); \
1508         *(p) = '\0'; \
1509 } while (0)
1510 #define STUNPUTC(p)             (--(p))
1511 #define STTOPC(p)               ((p)[-1])
1512 #define STADJUST(amount, p)     ((p) += (amount))
1513
1514 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1515 #define ungrabstackstr(s, p)    stunalloc(s)
1516 #define stackstrend()           ((void *)sstrend)
1517
1518
1519 /* ============ String helpers */
1520
1521 /*
1522  * prefix -- see if pfx is a prefix of string.
1523  */
1524 static char *
1525 prefix(const char *string, const char *pfx)
1526 {
1527         while (*pfx) {
1528                 if (*pfx++ != *string++)
1529                         return NULL;
1530         }
1531         return (char *) string;
1532 }
1533
1534 /*
1535  * Check for a valid number.  This should be elsewhere.
1536  */
1537 static int
1538 is_number(const char *p)
1539 {
1540         do {
1541                 if (!isdigit(*p))
1542                         return 0;
1543         } while (*++p != '\0');
1544         return 1;
1545 }
1546
1547 /*
1548  * Convert a string of digits to an integer, printing an error message on
1549  * failure.
1550  */
1551 static int
1552 number(const char *s)
1553 {
1554         if (!is_number(s))
1555                 ash_msg_and_raise_error(illnum, s);
1556         return atoi(s);
1557 }
1558
1559 /*
1560  * Produce a possibly single quoted string suitable as input to the shell.
1561  * The return string is allocated on the stack.
1562  */
1563 static char *
1564 single_quote(const char *s)
1565 {
1566         char *p;
1567
1568         STARTSTACKSTR(p);
1569
1570         do {
1571                 char *q;
1572                 size_t len;
1573
1574                 len = strchrnul(s, '\'') - s;
1575
1576                 q = p = makestrspace(len + 3, p);
1577
1578                 *q++ = '\'';
1579                 q = (char *)memcpy(q, s, len) + len;
1580                 *q++ = '\'';
1581                 s += len;
1582
1583                 STADJUST(q - p, p);
1584
1585                 len = strspn(s, "'");
1586                 if (!len)
1587                         break;
1588
1589                 q = p = makestrspace(len + 3, p);
1590
1591                 *q++ = '"';
1592                 q = (char *)memcpy(q, s, len) + len;
1593                 *q++ = '"';
1594                 s += len;
1595
1596                 STADJUST(q - p, p);
1597         } while (*s);
1598
1599         USTPUTC(0, p);
1600
1601         return stackblock();
1602 }
1603
1604
1605 /* ============ nextopt */
1606
1607 static char **argptr;                  /* argument list for builtin commands */
1608 static char *optionarg;                /* set by nextopt (like getopt) */
1609 static char *optptr;                   /* used by nextopt */
1610
1611 /*
1612  * XXX - should get rid of. Have all builtins use getopt(3).
1613  * The library getopt must have the BSD extension static variable
1614  * "optreset", otherwise it can't be used within the shell safely.
1615  *
1616  * Standard option processing (a la getopt) for builtin routines.
1617  * The only argument that is passed to nextopt is the option string;
1618  * the other arguments are unnecessary. It returns the character,
1619  * or '\0' on end of input.
1620  */
1621 static int
1622 nextopt(const char *optstring)
1623 {
1624         char *p;
1625         const char *q;
1626         char c;
1627
1628         p = optptr;
1629         if (p == NULL || *p == '\0') {
1630                 /* We ate entire "-param", take next one */
1631                 p = *argptr;
1632                 if (p == NULL)
1633                         return '\0';
1634                 if (*p != '-')
1635                         return '\0';
1636                 if (*++p == '\0') /* just "-" ? */
1637                         return '\0';
1638                 argptr++;
1639                 if (LONE_DASH(p)) /* "--" ? */
1640                         return '\0';
1641                 /* p => next "-param" */
1642         }
1643         /* p => some option char in the middle of a "-param" */
1644         c = *p++;
1645         for (q = optstring; *q != c;) {
1646                 if (*q == '\0')
1647                         ash_msg_and_raise_error("illegal option -%c", c);
1648                 if (*++q == ':')
1649                         q++;
1650         }
1651         if (*++q == ':') {
1652                 if (*p == '\0') {
1653                         p = *argptr++;
1654                         if (p == NULL)
1655                                 ash_msg_and_raise_error("no arg for -%c option", c);
1656                 }
1657                 optionarg = p;
1658                 p = NULL;
1659         }
1660         optptr = p;
1661         return c;
1662 }
1663
1664
1665 /* ============ Shell variables */
1666
1667 /*
1668  * The parsefile structure pointed to by the global variable parsefile
1669  * contains information about the current file being read.
1670  */
1671 struct shparam {
1672         int nparam;             /* # of positional parameters (without $0) */
1673 #if ENABLE_ASH_GETOPTS
1674         int optind;             /* next parameter to be processed by getopts */
1675         int optoff;             /* used by getopts */
1676 #endif
1677         unsigned char malloced; /* if parameter list dynamically allocated */
1678         char **p;               /* parameter list */
1679 };
1680
1681 /*
1682  * Free the list of positional parameters.
1683  */
1684 static void
1685 freeparam(volatile struct shparam *param)
1686 {
1687         if (param->malloced) {
1688                 char **ap, **ap1;
1689                 ap = ap1 = param->p;
1690                 while (*ap)
1691                         free(*ap++);
1692                 free(ap1);
1693         }
1694 }
1695
1696 #if ENABLE_ASH_GETOPTS
1697 static void getoptsreset(const char *value);
1698 #endif
1699
1700 struct var {
1701         struct var *next;               /* next entry in hash list */
1702         int flags;                      /* flags are defined above */
1703         const char *text;               /* name=value */
1704         void (*func)(const char *);     /* function to be called when  */
1705                                         /* the variable gets set/unset */
1706 };
1707
1708 struct localvar {
1709         struct localvar *next;          /* next local variable in list */
1710         struct var *vp;                 /* the variable that was made local */
1711         int flags;                      /* saved flags */
1712         const char *text;               /* saved text */
1713 };
1714
1715 /* flags */
1716 #define VEXPORT         0x01    /* variable is exported */
1717 #define VREADONLY       0x02    /* variable cannot be modified */
1718 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1719 #define VTEXTFIXED      0x08    /* text is statically allocated */
1720 #define VSTACK          0x10    /* text is allocated on the stack */
1721 #define VUNSET          0x20    /* the variable is not set */
1722 #define VNOFUNC         0x40    /* don't call the callback function */
1723 #define VNOSET          0x80    /* do not set variable - just readonly test */
1724 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1725 #if ENABLE_ASH_RANDOM_SUPPORT
1726 # define VDYNAMIC       0x200   /* dynamic variable */
1727 #else
1728 # define VDYNAMIC       0
1729 #endif
1730
1731 #ifdef IFS_BROKEN
1732 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1733 #define defifs (defifsvar + 4)
1734 #else
1735 static const char defifs[] ALIGN1 = " \t\n";
1736 #endif
1737
1738
1739 /* Need to be before varinit_data[] */
1740 #if ENABLE_LOCALE_SUPPORT
1741 static void
1742 change_lc_all(const char *value)
1743 {
1744         if (value && *value != '\0')
1745                 setlocale(LC_ALL, value);
1746 }
1747 static void
1748 change_lc_ctype(const char *value)
1749 {
1750         if (value && *value != '\0')
1751                 setlocale(LC_CTYPE, value);
1752 }
1753 #endif
1754 #if ENABLE_ASH_MAIL
1755 static void chkmail(void);
1756 static void changemail(const char *);
1757 #endif
1758 static void changepath(const char *);
1759 #if ENABLE_ASH_RANDOM_SUPPORT
1760 static void change_random(const char *);
1761 #endif
1762
1763 static const struct {
1764         int flags;
1765         const char *text;
1766         void (*func)(const char *);
1767 } varinit_data[] = {
1768 #ifdef IFS_BROKEN
1769         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1770 #else
1771         { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0"     , NULL            },
1772 #endif
1773 #if ENABLE_ASH_MAIL
1774         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0"    , changemail      },
1775         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail      },
1776 #endif
1777         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1778         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1779         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1780         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1781 #if ENABLE_ASH_GETOPTS
1782         { VSTRFIXED|VTEXTFIXED       , "OPTIND=1"  , getoptsreset    },
1783 #endif
1784 #if ENABLE_ASH_RANDOM_SUPPORT
1785         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1786 #endif
1787 #if ENABLE_LOCALE_SUPPORT
1788         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0"  , change_lc_all   },
1789         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1790 #endif
1791 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1792         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL            },
1793 #endif
1794 };
1795
1796 struct redirtab;
1797
1798 struct globals_var {
1799         struct shparam shellparam;      /* $@ current positional parameters */
1800         struct redirtab *redirlist;
1801         int g_nullredirs;
1802         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1803         struct var *vartab[VTABSIZE];
1804         struct var varinit[ARRAY_SIZE(varinit_data)];
1805 };
1806 extern struct globals_var *const ash_ptr_to_globals_var;
1807 #define G_var (*ash_ptr_to_globals_var)
1808 #define shellparam    (G_var.shellparam   )
1809 //#define redirlist     (G_var.redirlist    )
1810 #define g_nullredirs  (G_var.g_nullredirs )
1811 #define preverrout_fd (G_var.preverrout_fd)
1812 #define vartab        (G_var.vartab       )
1813 #define varinit       (G_var.varinit      )
1814 #define INIT_G_var() do { \
1815         unsigned i; \
1816         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1817         barrier(); \
1818         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1819                 varinit[i].flags = varinit_data[i].flags; \
1820                 varinit[i].text  = varinit_data[i].text; \
1821                 varinit[i].func  = varinit_data[i].func; \
1822         } \
1823 } while (0)
1824
1825 #define vifs      varinit[0]
1826 #if ENABLE_ASH_MAIL
1827 # define vmail    (&vifs)[1]
1828 # define vmpath   (&vmail)[1]
1829 # define vpath    (&vmpath)[1]
1830 #else
1831 # define vpath    (&vifs)[1]
1832 #endif
1833 #define vps1      (&vpath)[1]
1834 #define vps2      (&vps1)[1]
1835 #define vps4      (&vps2)[1]
1836 #if ENABLE_ASH_GETOPTS
1837 # define voptind  (&vps4)[1]
1838 # if ENABLE_ASH_RANDOM_SUPPORT
1839 #  define vrandom (&voptind)[1]
1840 # endif
1841 #else
1842 # if ENABLE_ASH_RANDOM_SUPPORT
1843 #  define vrandom (&vps4)[1]
1844 # endif
1845 #endif
1846
1847 /*
1848  * The following macros access the values of the above variables.
1849  * They have to skip over the name.  They return the null string
1850  * for unset variables.
1851  */
1852 #define ifsval()        (vifs.text + 4)
1853 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1854 #if ENABLE_ASH_MAIL
1855 # define mailval()      (vmail.text + 5)
1856 # define mpathval()     (vmpath.text + 9)
1857 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
1858 #endif
1859 #define pathval()       (vpath.text + 5)
1860 #define ps1val()        (vps1.text + 4)
1861 #define ps2val()        (vps2.text + 4)
1862 #define ps4val()        (vps4.text + 4)
1863 #if ENABLE_ASH_GETOPTS
1864 # define optindval()    (voptind.text + 7)
1865 #endif
1866
1867
1868 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
1869 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
1870
1871 #if ENABLE_ASH_GETOPTS
1872 static void
1873 getoptsreset(const char *value)
1874 {
1875         shellparam.optind = number(value);
1876         shellparam.optoff = -1;
1877 }
1878 #endif
1879
1880 /*
1881  * Return of a legal variable name (a letter or underscore followed by zero or
1882  * more letters, underscores, and digits).
1883  */
1884 static char *
1885 endofname(const char *name)
1886 {
1887         char *p;
1888
1889         p = (char *) name;
1890         if (!is_name(*p))
1891                 return p;
1892         while (*++p) {
1893                 if (!is_in_name(*p))
1894                         break;
1895         }
1896         return p;
1897 }
1898
1899 /*
1900  * Compares two strings up to the first = or '\0'.  The first
1901  * string must be terminated by '='; the second may be terminated by
1902  * either '=' or '\0'.
1903  */
1904 static int
1905 varcmp(const char *p, const char *q)
1906 {
1907         int c, d;
1908
1909         while ((c = *p) == (d = *q)) {
1910                 if (!c || c == '=')
1911                         goto out;
1912                 p++;
1913                 q++;
1914         }
1915         if (c == '=')
1916                 c = '\0';
1917         if (d == '=')
1918                 d = '\0';
1919  out:
1920         return c - d;
1921 }
1922
1923 static int
1924 varequal(const char *a, const char *b)
1925 {
1926         return !varcmp(a, b);
1927 }
1928
1929 /*
1930  * Find the appropriate entry in the hash table from the name.
1931  */
1932 static struct var **
1933 hashvar(const char *p)
1934 {
1935         unsigned hashval;
1936
1937         hashval = ((unsigned char) *p) << 4;
1938         while (*p && *p != '=')
1939                 hashval += (unsigned char) *p++;
1940         return &vartab[hashval % VTABSIZE];
1941 }
1942
1943 static int
1944 vpcmp(const void *a, const void *b)
1945 {
1946         return varcmp(*(const char **)a, *(const char **)b);
1947 }
1948
1949 /*
1950  * This routine initializes the builtin variables.
1951  */
1952 static void
1953 initvar(void)
1954 {
1955         struct var *vp;
1956         struct var *end;
1957         struct var **vpp;
1958
1959         /*
1960          * PS1 depends on uid
1961          */
1962 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1963         vps1.text = "PS1=\\w \\$ ";
1964 #else
1965         if (!geteuid())
1966                 vps1.text = "PS1=# ";
1967 #endif
1968         vp = varinit;
1969         end = vp + ARRAY_SIZE(varinit);
1970         do {
1971                 vpp = hashvar(vp->text);
1972                 vp->next = *vpp;
1973                 *vpp = vp;
1974         } while (++vp < end);
1975 }
1976
1977 static struct var **
1978 findvar(struct var **vpp, const char *name)
1979 {
1980         for (; *vpp; vpp = &(*vpp)->next) {
1981                 if (varequal((*vpp)->text, name)) {
1982                         break;
1983                 }
1984         }
1985         return vpp;
1986 }
1987
1988 /*
1989  * Find the value of a variable.  Returns NULL if not set.
1990  */
1991 static char *
1992 lookupvar(const char *name)
1993 {
1994         struct var *v;
1995
1996         v = *findvar(hashvar(name), name);
1997         if (v) {
1998 #if ENABLE_ASH_RANDOM_SUPPORT
1999         /*
2000          * Dynamic variables are implemented roughly the same way they are
2001          * in bash. Namely, they're "special" so long as they aren't unset.
2002          * As soon as they're unset, they're no longer dynamic, and dynamic
2003          * lookup will no longer happen at that point. -- PFM.
2004          */
2005                 if ((v->flags & VDYNAMIC))
2006                         (*v->func)(NULL);
2007 #endif
2008                 if (!(v->flags & VUNSET))
2009                         return strchrnul(v->text, '=') + 1;
2010         }
2011         return NULL;
2012 }
2013
2014 /*
2015  * Search the environment of a builtin command.
2016  */
2017 static char *
2018 bltinlookup(const char *name)
2019 {
2020         struct strlist *sp;
2021
2022         for (sp = cmdenviron; sp; sp = sp->next) {
2023                 if (varequal(sp->text, name))
2024                         return strchrnul(sp->text, '=') + 1;
2025         }
2026         return lookupvar(name);
2027 }
2028
2029 /*
2030  * Same as setvar except that the variable and value are passed in
2031  * the first argument as name=value.  Since the first argument will
2032  * be actually stored in the table, it should not be a string that
2033  * will go away.
2034  * Called with interrupts off.
2035  */
2036 static void
2037 setvareq(char *s, int flags)
2038 {
2039         struct var *vp, **vpp;
2040
2041         vpp = hashvar(s);
2042         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2043         vp = *findvar(vpp, s);
2044         if (vp) {
2045                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2046                         const char *n;
2047
2048                         if (flags & VNOSAVE)
2049                                 free(s);
2050                         n = vp->text;
2051                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2052                 }
2053
2054                 if (flags & VNOSET)
2055                         return;
2056
2057                 if (vp->func && (flags & VNOFUNC) == 0)
2058                         (*vp->func)(strchrnul(s, '=') + 1);
2059
2060                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2061                         free((char*)vp->text);
2062
2063                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2064         } else {
2065                 if (flags & VNOSET)
2066                         return;
2067                 /* not found */
2068                 vp = ckzalloc(sizeof(*vp));
2069                 vp->next = *vpp;
2070                 /*vp->func = NULL; - ckzalloc did it */
2071                 *vpp = vp;
2072         }
2073         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2074                 s = ckstrdup(s);
2075         vp->text = s;
2076         vp->flags = flags;
2077 }
2078
2079 /*
2080  * Set the value of a variable.  The flags argument is ored with the
2081  * flags of the variable.  If val is NULL, the variable is unset.
2082  */
2083 static void
2084 setvar(const char *name, const char *val, int flags)
2085 {
2086         char *p, *q;
2087         size_t namelen;
2088         char *nameeq;
2089         size_t vallen;
2090
2091         q = endofname(name);
2092         p = strchrnul(q, '=');
2093         namelen = p - name;
2094         if (!namelen || p != q)
2095                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2096         vallen = 0;
2097         if (val == NULL) {
2098                 flags |= VUNSET;
2099         } else {
2100                 vallen = strlen(val);
2101         }
2102         INT_OFF;
2103         nameeq = ckmalloc(namelen + vallen + 2);
2104         p = (char *)memcpy(nameeq, name, namelen) + namelen;
2105         if (val) {
2106                 *p++ = '=';
2107                 p = (char *)memcpy(p, val, vallen) + vallen;
2108         }
2109         *p = '\0';
2110         setvareq(nameeq, flags | VNOSAVE);
2111         INT_ON;
2112 }
2113
2114 #if ENABLE_ASH_GETOPTS
2115 /*
2116  * Safe version of setvar, returns 1 on success 0 on failure.
2117  */
2118 static int
2119 setvarsafe(const char *name, const char *val, int flags)
2120 {
2121         int err;
2122         volatile int saveint;
2123         struct jmploc *volatile savehandler = exception_handler;
2124         struct jmploc jmploc;
2125
2126         SAVE_INT(saveint);
2127         if (setjmp(jmploc.loc))
2128                 err = 1;
2129         else {
2130                 exception_handler = &jmploc;
2131                 setvar(name, val, flags);
2132                 err = 0;
2133         }
2134         exception_handler = savehandler;
2135         RESTORE_INT(saveint);
2136         return err;
2137 }
2138 #endif
2139
2140 /*
2141  * Unset the specified variable.
2142  */
2143 static int
2144 unsetvar(const char *s)
2145 {
2146         struct var **vpp;
2147         struct var *vp;
2148         int retval;
2149
2150         vpp = findvar(hashvar(s), s);
2151         vp = *vpp;
2152         retval = 2;
2153         if (vp) {
2154                 int flags = vp->flags;
2155
2156                 retval = 1;
2157                 if (flags & VREADONLY)
2158                         goto out;
2159 #if ENABLE_ASH_RANDOM_SUPPORT
2160                 vp->flags &= ~VDYNAMIC;
2161 #endif
2162                 if (flags & VUNSET)
2163                         goto ok;
2164                 if ((flags & VSTRFIXED) == 0) {
2165                         INT_OFF;
2166                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2167                                 free((char*)vp->text);
2168                         *vpp = vp->next;
2169                         free(vp);
2170                         INT_ON;
2171                 } else {
2172                         setvar(s, 0, 0);
2173                         vp->flags &= ~VEXPORT;
2174                 }
2175  ok:
2176                 retval = 0;
2177         }
2178  out:
2179         return retval;
2180 }
2181
2182 /*
2183  * Process a linked list of variable assignments.
2184  */
2185 static void
2186 listsetvar(struct strlist *list_set_var, int flags)
2187 {
2188         struct strlist *lp = list_set_var;
2189
2190         if (!lp)
2191                 return;
2192         INT_OFF;
2193         do {
2194                 setvareq(lp->text, flags);
2195                 lp = lp->next;
2196         } while (lp);
2197         INT_ON;
2198 }
2199
2200 /*
2201  * Generate a list of variables satisfying the given conditions.
2202  */
2203 static char **
2204 listvars(int on, int off, char ***end)
2205 {
2206         struct var **vpp;
2207         struct var *vp;
2208         char **ep;
2209         int mask;
2210
2211         STARTSTACKSTR(ep);
2212         vpp = vartab;
2213         mask = on | off;
2214         do {
2215                 for (vp = *vpp; vp; vp = vp->next) {
2216                         if ((vp->flags & mask) == on) {
2217                                 if (ep == stackstrend())
2218                                         ep = growstackstr();
2219                                 *ep++ = (char *) vp->text;
2220                         }
2221                 }
2222         } while (++vpp < vartab + VTABSIZE);
2223         if (ep == stackstrend())
2224                 ep = growstackstr();
2225         if (end)
2226                 *end = ep;
2227         *ep++ = NULL;
2228         return grabstackstr(ep);
2229 }
2230
2231
2232 /* ============ Path search helper
2233  *
2234  * The variable path (passed by reference) should be set to the start
2235  * of the path before the first call; padvance will update
2236  * this value as it proceeds.  Successive calls to padvance will return
2237  * the possible path expansions in sequence.  If an option (indicated by
2238  * a percent sign) appears in the path entry then the global variable
2239  * pathopt will be set to point to it; otherwise pathopt will be set to
2240  * NULL.
2241  */
2242 static const char *pathopt;     /* set by padvance */
2243
2244 static char *
2245 padvance(const char **path, const char *name)
2246 {
2247         const char *p;
2248         char *q;
2249         const char *start;
2250         size_t len;
2251
2252         if (*path == NULL)
2253                 return NULL;
2254         start = *path;
2255         for (p = start; *p && *p != ':' && *p != '%'; p++)
2256                 continue;
2257         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2258         while (stackblocksize() < len)
2259                 growstackblock();
2260         q = stackblock();
2261         if (p != start) {
2262                 memcpy(q, start, p - start);
2263                 q += p - start;
2264                 *q++ = '/';
2265         }
2266         strcpy(q, name);
2267         pathopt = NULL;
2268         if (*p == '%') {
2269                 pathopt = ++p;
2270                 while (*p && *p != ':')
2271                         p++;
2272         }
2273         if (*p == ':')
2274                 *path = p + 1;
2275         else
2276                 *path = NULL;
2277         return stalloc(len);
2278 }
2279
2280
2281 /* ============ Prompt */
2282
2283 static smallint doprompt;                   /* if set, prompt the user */
2284 static smallint needprompt;                 /* true if interactive and at start of line */
2285
2286 #if ENABLE_FEATURE_EDITING
2287 static line_input_t *line_input_state;
2288 static const char *cmdedit_prompt;
2289 static void
2290 putprompt(const char *s)
2291 {
2292         if (ENABLE_ASH_EXPAND_PRMT) {
2293                 free((char*)cmdedit_prompt);
2294                 cmdedit_prompt = ckstrdup(s);
2295                 return;
2296         }
2297         cmdedit_prompt = s;
2298 }
2299 #else
2300 static void
2301 putprompt(const char *s)
2302 {
2303         out2str(s);
2304 }
2305 #endif
2306
2307 #if ENABLE_ASH_EXPAND_PRMT
2308 /* expandstr() needs parsing machinery, so it is far away ahead... */
2309 static const char *expandstr(const char *ps);
2310 #else
2311 #define expandstr(s) s
2312 #endif
2313
2314 static void
2315 setprompt(int whichprompt)
2316 {
2317         const char *prompt;
2318 #if ENABLE_ASH_EXPAND_PRMT
2319         struct stackmark smark;
2320 #endif
2321
2322         needprompt = 0;
2323
2324         switch (whichprompt) {
2325         case 1:
2326                 prompt = ps1val();
2327                 break;
2328         case 2:
2329                 prompt = ps2val();
2330                 break;
2331         default:                        /* 0 */
2332                 prompt = nullstr;
2333         }
2334 #if ENABLE_ASH_EXPAND_PRMT
2335         setstackmark(&smark);
2336         stalloc(stackblocksize());
2337 #endif
2338         putprompt(expandstr(prompt));
2339 #if ENABLE_ASH_EXPAND_PRMT
2340         popstackmark(&smark);
2341 #endif
2342 }
2343
2344
2345 /* ============ The cd and pwd commands */
2346
2347 #define CD_PHYSICAL 1
2348 #define CD_PRINT 2
2349
2350 static int docd(const char *, int);
2351
2352 static int
2353 cdopt(void)
2354 {
2355         int flags = 0;
2356         int i, j;
2357
2358         j = 'L';
2359         while ((i = nextopt("LP"))) {
2360                 if (i != j) {
2361                         flags ^= CD_PHYSICAL;
2362                         j = i;
2363                 }
2364         }
2365
2366         return flags;
2367 }
2368
2369 /*
2370  * Update curdir (the name of the current directory) in response to a
2371  * cd command.
2372  */
2373 static const char *
2374 updatepwd(const char *dir)
2375 {
2376         char *new;
2377         char *p;
2378         char *cdcomppath;
2379         const char *lim;
2380
2381         cdcomppath = ststrdup(dir);
2382         STARTSTACKSTR(new);
2383         if (*dir != '/') {
2384                 if (curdir == nullstr)
2385                         return 0;
2386                 new = stack_putstr(curdir, new);
2387         }
2388         new = makestrspace(strlen(dir) + 2, new);
2389         lim = (char *)stackblock() + 1;
2390         if (*dir != '/') {
2391                 if (new[-1] != '/')
2392                         USTPUTC('/', new);
2393                 if (new > lim && *lim == '/')
2394                         lim++;
2395         } else {
2396                 USTPUTC('/', new);
2397                 cdcomppath++;
2398                 if (dir[1] == '/' && dir[2] != '/') {
2399                         USTPUTC('/', new);
2400                         cdcomppath++;
2401                         lim++;
2402                 }
2403         }
2404         p = strtok(cdcomppath, "/");
2405         while (p) {
2406                 switch (*p) {
2407                 case '.':
2408                         if (p[1] == '.' && p[2] == '\0') {
2409                                 while (new > lim) {
2410                                         STUNPUTC(new);
2411                                         if (new[-1] == '/')
2412                                                 break;
2413                                 }
2414                                 break;
2415                         }
2416                         if (p[1] == '\0')
2417                                 break;
2418                         /* fall through */
2419                 default:
2420                         new = stack_putstr(p, new);
2421                         USTPUTC('/', new);
2422                 }
2423                 p = strtok(0, "/");
2424         }
2425         if (new > lim)
2426                 STUNPUTC(new);
2427         *new = 0;
2428         return stackblock();
2429 }
2430
2431 /*
2432  * Find out what the current directory is. If we already know the current
2433  * directory, this routine returns immediately.
2434  */
2435 static char *
2436 getpwd(void)
2437 {
2438         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2439         return dir ? dir : nullstr;
2440 }
2441
2442 static void
2443 setpwd(const char *val, int setold)
2444 {
2445         char *oldcur, *dir;
2446
2447         oldcur = dir = curdir;
2448
2449         if (setold) {
2450                 setvar("OLDPWD", oldcur, VEXPORT);
2451         }
2452         INT_OFF;
2453         if (physdir != nullstr) {
2454                 if (physdir != oldcur)
2455                         free(physdir);
2456                 physdir = nullstr;
2457         }
2458         if (oldcur == val || !val) {
2459                 char *s = getpwd();
2460                 physdir = s;
2461                 if (!val)
2462                         dir = s;
2463         } else
2464                 dir = ckstrdup(val);
2465         if (oldcur != dir && oldcur != nullstr) {
2466                 free(oldcur);
2467         }
2468         curdir = dir;
2469         INT_ON;
2470         setvar("PWD", dir, VEXPORT);
2471 }
2472
2473 static void hashcd(void);
2474
2475 /*
2476  * Actually do the chdir.  We also call hashcd to let the routines in exec.c
2477  * know that the current directory has changed.
2478  */
2479 static int
2480 docd(const char *dest, int flags)
2481 {
2482         const char *dir = 0;
2483         int err;
2484
2485         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2486
2487         INT_OFF;
2488         if (!(flags & CD_PHYSICAL)) {
2489                 dir = updatepwd(dest);
2490                 if (dir)
2491                         dest = dir;
2492         }
2493         err = chdir(dest);
2494         if (err)
2495                 goto out;
2496         setpwd(dir, 1);
2497         hashcd();
2498  out:
2499         INT_ON;
2500         return err;
2501 }
2502
2503 static int
2504 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2505 {
2506         const char *dest;
2507         const char *path;
2508         const char *p;
2509         char c;
2510         struct stat statb;
2511         int flags;
2512
2513         flags = cdopt();
2514         dest = *argptr;
2515         if (!dest)
2516                 dest = bltinlookup(homestr);
2517         else if (LONE_DASH(dest)) {
2518                 dest = bltinlookup("OLDPWD");
2519                 flags |= CD_PRINT;
2520         }
2521         if (!dest)
2522                 dest = nullstr;
2523         if (*dest == '/')
2524                 goto step7;
2525         if (*dest == '.') {
2526                 c = dest[1];
2527  dotdot:
2528                 switch (c) {
2529                 case '\0':
2530                 case '/':
2531                         goto step6;
2532                 case '.':
2533                         c = dest[2];
2534                         if (c != '.')
2535                                 goto dotdot;
2536                 }
2537         }
2538         if (!*dest)
2539                 dest = ".";
2540         path = bltinlookup("CDPATH");
2541         if (!path) {
2542  step6:
2543  step7:
2544                 p = dest;
2545                 goto docd;
2546         }
2547         do {
2548                 c = *path;
2549                 p = padvance(&path, dest);
2550                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2551                         if (c && c != ':')
2552                                 flags |= CD_PRINT;
2553  docd:
2554                         if (!docd(p, flags))
2555                                 goto out;
2556                         break;
2557                 }
2558         } while (path);
2559         ash_msg_and_raise_error("can't cd to %s", dest);
2560         /* NOTREACHED */
2561  out:
2562         if (flags & CD_PRINT)
2563                 out1fmt(snlfmt, curdir);
2564         return 0;
2565 }
2566
2567 static int
2568 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2569 {
2570         int flags;
2571         const char *dir = curdir;
2572
2573         flags = cdopt();
2574         if (flags) {
2575                 if (physdir == nullstr)
2576                         setpwd(dir, 0);
2577                 dir = physdir;
2578         }
2579         out1fmt(snlfmt, dir);
2580         return 0;
2581 }
2582
2583
2584 /* ============ ... */
2585
2586
2587 #define IBUFSIZ COMMON_BUFSIZE
2588 /* buffer for top level input file */
2589 #define basebuf bb_common_bufsiz1
2590
2591 /* Syntax classes */
2592 #define CWORD     0             /* character is nothing special */
2593 #define CNL       1             /* newline character */
2594 #define CBACK     2             /* a backslash character */
2595 #define CSQUOTE   3             /* single quote */
2596 #define CDQUOTE   4             /* double quote */
2597 #define CENDQUOTE 5             /* a terminating quote */
2598 #define CBQUOTE   6             /* backwards single quote */
2599 #define CVAR      7             /* a dollar sign */
2600 #define CENDVAR   8             /* a '}' character */
2601 #define CLP       9             /* a left paren in arithmetic */
2602 #define CRP      10             /* a right paren in arithmetic */
2603 #define CENDFILE 11             /* end of file */
2604 #define CCTL     12             /* like CWORD, except it must be escaped */
2605 #define CSPCL    13             /* these terminate a word */
2606 #define CIGN     14             /* character should be ignored */
2607
2608 #if ENABLE_ASH_ALIAS
2609 #define SYNBASE       130
2610 #define PEOF         -130
2611 #define PEOA         -129
2612 #define PEOA_OR_PEOF PEOA
2613 #else
2614 #define SYNBASE       129
2615 #define PEOF         -129
2616 #define PEOA_OR_PEOF PEOF
2617 #endif
2618
2619 /* number syntax index */
2620 #define BASESYNTAX 0    /* not in quotes */
2621 #define DQSYNTAX   1    /* in double quotes */
2622 #define SQSYNTAX   2    /* in single quotes */
2623 #define ARISYNTAX  3    /* in arithmetic */
2624 #define PSSYNTAX   4    /* prompt */
2625
2626 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2627 #define USE_SIT_FUNCTION
2628 #endif
2629
2630 #if ENABLE_ASH_MATH_SUPPORT
2631 static const char S_I_T[][4] = {
2632 #if ENABLE_ASH_ALIAS
2633         { CSPCL, CIGN, CIGN, CIGN },            /* 0, PEOA */
2634 #endif
2635         { CSPCL, CWORD, CWORD, CWORD },         /* 1, ' ' */
2636         { CNL, CNL, CNL, CNL },                 /* 2, \n */
2637         { CWORD, CCTL, CCTL, CWORD },           /* 3, !*-/:=?[]~ */
2638         { CDQUOTE, CENDQUOTE, CWORD, CWORD },   /* 4, '"' */
2639         { CVAR, CVAR, CWORD, CVAR },            /* 5, $ */
2640         { CSQUOTE, CWORD, CENDQUOTE, CWORD },   /* 6, "'" */
2641         { CSPCL, CWORD, CWORD, CLP },           /* 7, ( */
2642         { CSPCL, CWORD, CWORD, CRP },           /* 8, ) */
2643         { CBACK, CBACK, CCTL, CBACK },          /* 9, \ */
2644         { CBQUOTE, CBQUOTE, CWORD, CBQUOTE },   /* 10, ` */
2645         { CENDVAR, CENDVAR, CWORD, CENDVAR },   /* 11, } */
2646 #ifndef USE_SIT_FUNCTION
2647         { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2648         { CWORD, CWORD, CWORD, CWORD },         /* 13, 0-9A-Za-z */
2649         { CCTL, CCTL, CCTL, CCTL }              /* 14, CTLESC ... */
2650 #endif
2651 };
2652 #else
2653 static const char S_I_T[][3] = {
2654 #if ENABLE_ASH_ALIAS
2655         { CSPCL, CIGN, CIGN },                  /* 0, PEOA */
2656 #endif
2657         { CSPCL, CWORD, CWORD },                /* 1, ' ' */
2658         { CNL, CNL, CNL },                      /* 2, \n */
2659         { CWORD, CCTL, CCTL },                  /* 3, !*-/:=?[]~ */
2660         { CDQUOTE, CENDQUOTE, CWORD },          /* 4, '"' */
2661         { CVAR, CVAR, CWORD },                  /* 5, $ */
2662         { CSQUOTE, CWORD, CENDQUOTE },          /* 6, "'" */
2663         { CSPCL, CWORD, CWORD },                /* 7, ( */
2664         { CSPCL, CWORD, CWORD },                /* 8, ) */
2665         { CBACK, CBACK, CCTL },                 /* 9, \ */
2666         { CBQUOTE, CBQUOTE, CWORD },            /* 10, ` */
2667         { CENDVAR, CENDVAR, CWORD },            /* 11, } */
2668 #ifndef USE_SIT_FUNCTION
2669         { CENDFILE, CENDFILE, CENDFILE },       /* 12, PEOF */
2670         { CWORD, CWORD, CWORD },                /* 13, 0-9A-Za-z */
2671         { CCTL, CCTL, CCTL }                    /* 14, CTLESC ... */
2672 #endif
2673 };
2674 #endif /* ASH_MATH_SUPPORT */
2675
2676 #ifdef USE_SIT_FUNCTION
2677
2678 static int
2679 SIT(int c, int syntax)
2680 {
2681         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2682 #if ENABLE_ASH_ALIAS
2683         static const char syntax_index_table[] ALIGN1 = {
2684                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2685                 7, 8, 3, 3, 3, 3, 1, 1,         /* "()*-/:;<" */
2686                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2687                 11, 3                           /* "}~" */
2688         };
2689 #else
2690         static const char syntax_index_table[] ALIGN1 = {
2691                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2692                 6, 7, 2, 2, 2, 2, 0, 0,         /* "()*-/:;<" */
2693                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2694                 10, 2                           /* "}~" */
2695         };
2696 #endif
2697         const char *s;
2698         int indx;
2699
2700         if (c == PEOF)          /* 2^8+2 */
2701                 return CENDFILE;
2702 #if ENABLE_ASH_ALIAS
2703         if (c == PEOA)          /* 2^8+1 */
2704                 indx = 0;
2705         else
2706 #endif
2707
2708         if ((unsigned char)c >= (unsigned char)(CTLESC)
2709          && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2710         ) {
2711                 return CCTL;
2712         }
2713         s = strchrnul(spec_symbls, c);
2714         if (*s == '\0')
2715                 return CWORD;
2716         indx = syntax_index_table[s - spec_symbls];
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                  * $ bash -c './sleep5intoff; echo hi'
4683                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4684                  * $ _
4685                  */
4686                 dowait(DOWAIT_BLOCK, jp);
4687         }
4688         INT_ON;
4689
4690         st = getstatus(jp);
4691 #if JOBS
4692         if (jp->jobctl) {
4693                 xtcsetpgrp(ttyfd, rootpid);
4694                 /*
4695                  * This is truly gross.
4696                  * If we're doing job control, then we did a TIOCSPGRP which
4697                  * caused us (the shell) to no longer be in the controlling
4698                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
4699                  * intuit from the subprocess exit status whether a SIGINT
4700                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
4701                  */
4702                 if (jp->sigint) /* TODO: do the same with all signals */
4703                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
4704         }
4705         if (jp->state == JOBDONE)
4706 #endif
4707                 freejob(jp);
4708         return st;
4709 }
4710
4711 /*
4712  * return 1 if there are stopped jobs, otherwise 0
4713  */
4714 static int
4715 stoppedjobs(void)
4716 {
4717         struct job *jp;
4718         int retval;
4719
4720         retval = 0;
4721         if (job_warning)
4722                 goto out;
4723         jp = curjob;
4724         if (jp && jp->state == JOBSTOPPED) {
4725                 out2str("You have stopped jobs.\n");
4726                 job_warning = 2;
4727                 retval++;
4728         }
4729  out:
4730         return retval;
4731 }
4732
4733
4734 /* ============ redir.c
4735  *
4736  * Code for dealing with input/output redirection.
4737  */
4738
4739 #define EMPTY -2                /* marks an unused slot in redirtab */
4740 #define CLOSED -3               /* marks a slot of previously-closed fd */
4741
4742 /*
4743  * Open a file in noclobber mode.
4744  * The code was copied from bash.
4745  */
4746 static int
4747 noclobberopen(const char *fname)
4748 {
4749         int r, fd;
4750         struct stat finfo, finfo2;
4751
4752         /*
4753          * If the file exists and is a regular file, return an error
4754          * immediately.
4755          */
4756         r = stat(fname, &finfo);
4757         if (r == 0 && S_ISREG(finfo.st_mode)) {
4758                 errno = EEXIST;
4759                 return -1;
4760         }
4761
4762         /*
4763          * If the file was not present (r != 0), make sure we open it
4764          * exclusively so that if it is created before we open it, our open
4765          * will fail.  Make sure that we do not truncate an existing file.
4766          * Note that we don't turn on O_EXCL unless the stat failed -- if the
4767          * file was not a regular file, we leave O_EXCL off.
4768          */
4769         if (r != 0)
4770                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4771         fd = open(fname, O_WRONLY|O_CREAT, 0666);
4772
4773         /* If the open failed, return the file descriptor right away. */
4774         if (fd < 0)
4775                 return fd;
4776
4777         /*
4778          * OK, the open succeeded, but the file may have been changed from a
4779          * non-regular file to a regular file between the stat and the open.
4780          * We are assuming that the O_EXCL open handles the case where FILENAME
4781          * did not exist and is symlinked to an existing file between the stat
4782          * and open.
4783          */
4784
4785         /*
4786          * If we can open it and fstat the file descriptor, and neither check
4787          * revealed that it was a regular file, and the file has not been
4788          * replaced, return the file descriptor.
4789          */
4790         if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4791          && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4792                 return fd;
4793
4794         /* The file has been replaced.  badness. */
4795         close(fd);
4796         errno = EEXIST;
4797         return -1;
4798 }
4799
4800 /*
4801  * Handle here documents.  Normally we fork off a process to write the
4802  * data to a pipe.  If the document is short, we can stuff the data in
4803  * the pipe without forking.
4804  */
4805 /* openhere needs this forward reference */
4806 static void expandhere(union node *arg, int fd);
4807 static int
4808 openhere(union node *redir)
4809 {
4810         int pip[2];
4811         size_t len = 0;
4812
4813         if (pipe(pip) < 0)
4814                 ash_msg_and_raise_error("pipe call failed");
4815         if (redir->type == NHERE) {
4816                 len = strlen(redir->nhere.doc->narg.text);
4817                 if (len <= PIPE_BUF) {
4818                         full_write(pip[1], redir->nhere.doc->narg.text, len);
4819                         goto out;
4820                 }
4821         }
4822         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4823                 /* child */
4824                 close(pip[0]);
4825                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
4826                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4827                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
4828                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4829                 signal(SIGPIPE, SIG_DFL);
4830                 if (redir->type == NHERE)
4831                         full_write(pip[1], redir->nhere.doc->narg.text, len);
4832                 else /* NXHERE */
4833                         expandhere(redir->nhere.doc, pip[1]);
4834                 _exit(EXIT_SUCCESS);
4835         }
4836  out:
4837         close(pip[1]);
4838         return pip[0];
4839 }
4840
4841 static int
4842 openredirect(union node *redir)
4843 {
4844         char *fname;
4845         int f;
4846
4847         switch (redir->nfile.type) {
4848         case NFROM:
4849                 fname = redir->nfile.expfname;
4850                 f = open(fname, O_RDONLY);
4851                 if (f < 0)
4852                         goto eopen;
4853                 break;
4854         case NFROMTO:
4855                 fname = redir->nfile.expfname;
4856                 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4857                 if (f < 0)
4858                         goto ecreate;
4859                 break;
4860         case NTO:
4861 #if ENABLE_ASH_BASH_COMPAT
4862         case NTO2:
4863 #endif
4864                 /* Take care of noclobber mode. */
4865                 if (Cflag) {
4866                         fname = redir->nfile.expfname;
4867                         f = noclobberopen(fname);
4868                         if (f < 0)
4869                                 goto ecreate;
4870                         break;
4871                 }
4872                 /* FALLTHROUGH */
4873         case NCLOBBER:
4874                 fname = redir->nfile.expfname;
4875                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4876                 if (f < 0)
4877                         goto ecreate;
4878                 break;
4879         case NAPPEND:
4880                 fname = redir->nfile.expfname;
4881                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4882                 if (f < 0)
4883                         goto ecreate;
4884                 break;
4885         default:
4886 #if DEBUG
4887                 abort();
4888 #endif
4889                 /* Fall through to eliminate warning. */
4890 /* Our single caller does this itself */
4891 //      case NTOFD:
4892 //      case NFROMFD:
4893 //              f = -1;
4894 //              break;
4895         case NHERE:
4896         case NXHERE:
4897                 f = openhere(redir);
4898                 break;
4899         }
4900
4901         return f;
4902  ecreate:
4903         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4904  eopen:
4905         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4906 }
4907
4908 /*
4909  * Copy a file descriptor to be >= to.  Returns -1
4910  * if the source file descriptor is closed, EMPTY if there are no unused
4911  * file descriptors left.
4912  */
4913 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4914  * old code was doing close(to) prior to copyfd() to achieve the same */
4915 enum {
4916         COPYFD_EXACT   = (int)~(INT_MAX),
4917         COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4918 };
4919 static int
4920 copyfd(int from, int to)
4921 {
4922         int newfd;
4923
4924         if (to & COPYFD_EXACT) {
4925                 to &= ~COPYFD_EXACT;
4926                 /*if (from != to)*/
4927                         newfd = dup2(from, to);
4928         } else {
4929                 newfd = fcntl(from, F_DUPFD, to);
4930         }
4931         if (newfd < 0) {
4932                 if (errno == EMFILE)
4933                         return EMPTY;
4934                 /* Happens when source fd is not open: try "echo >&99" */
4935                 ash_msg_and_raise_error("%d: %m", from);
4936         }
4937         return newfd;
4938 }
4939
4940 /* Struct def and variable are moved down to the first usage site */
4941 struct two_fd_t {
4942         int orig, copy;
4943 };
4944 struct redirtab {
4945         struct redirtab *next;
4946         int nullredirs;
4947         int pair_count;
4948         struct two_fd_t two_fd[0];
4949 };
4950 #define redirlist (G_var.redirlist)
4951
4952 static int need_to_remember(struct redirtab *rp, int fd)
4953 {
4954         int i;
4955
4956         if (!rp) /* remembering was not requested */
4957                 return 0;
4958
4959         for (i = 0; i < rp->pair_count; i++) {
4960                 if (rp->two_fd[i].orig == fd) {
4961                         /* already remembered */
4962                         return 0;
4963                 }
4964         }
4965         return 1;
4966 }
4967
4968 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4969 static int is_hidden_fd(struct redirtab *rp, int fd)
4970 {
4971         int i;
4972         struct parsefile *pf;
4973
4974         if (fd == -1)
4975                 return 0;
4976         pf = g_parsefile;
4977         while (pf) {
4978                 if (fd == pf->fd) {
4979                         return 1;
4980                 }
4981                 pf = pf->prev;
4982         }
4983         if (!rp)
4984                 return 0;
4985         fd |= COPYFD_RESTORE;
4986         for (i = 0; i < rp->pair_count; i++) {
4987                 if (rp->two_fd[i].copy == fd) {
4988                         return 1;
4989                 }
4990         }
4991         return 0;
4992 }
4993
4994 /*
4995  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
4996  * old file descriptors are stashed away so that the redirection can be
4997  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
4998  * standard output, and the standard error if it becomes a duplicate of
4999  * stdout, is saved in memory.
5000  */
5001 /* flags passed to redirect */
5002 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5003 #define REDIR_SAVEFD2 03        /* set preverrout */
5004 static void
5005 redirect(union node *redir, int flags)
5006 {
5007         struct redirtab *sv;
5008         int sv_pos;
5009         int i;
5010         int fd;
5011         int newfd;
5012         int copied_fd2 = -1;
5013
5014         g_nullredirs++;
5015         if (!redir) {
5016                 return;
5017         }
5018
5019         sv = NULL;
5020         sv_pos = 0;
5021         INT_OFF;
5022         if (flags & REDIR_PUSH) {
5023                 union node *tmp = redir;
5024                 do {
5025                         sv_pos++;
5026 #if ENABLE_ASH_BASH_COMPAT
5027                         if (redir->nfile.type == NTO2)
5028                                 sv_pos++;
5029 #endif
5030                         tmp = tmp->nfile.next;
5031                 } while (tmp);
5032                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5033                 sv->next = redirlist;
5034                 sv->pair_count = sv_pos;
5035                 redirlist = sv;
5036                 sv->nullredirs = g_nullredirs - 1;
5037                 g_nullredirs = 0;
5038                 while (sv_pos > 0) {
5039                         sv_pos--;
5040                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5041                 }
5042         }
5043
5044         do {
5045                 fd = redir->nfile.fd;
5046                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5047                         int right_fd = redir->ndup.dupfd;
5048                         /* redirect from/to same file descriptor? */
5049                         if (right_fd == fd)
5050                                 continue;
5051                         /* echo >&10 and 10 is a fd opened to the sh script? */
5052                         if (is_hidden_fd(sv, right_fd)) {
5053                                 errno = EBADF; /* as if it is closed */
5054                                 ash_msg_and_raise_error("%d: %m", right_fd);
5055                         }
5056                         newfd = -1;
5057                 } else {
5058                         newfd = openredirect(redir); /* always >= 0 */
5059                         if (fd == newfd) {
5060                                 /* Descriptor wasn't open before redirect.
5061                                  * Mark it for close in the future */
5062                                 if (need_to_remember(sv, fd)) {
5063                                         goto remember_to_close;
5064                                 }
5065                                 continue;
5066                         }
5067                 }
5068 #if ENABLE_ASH_BASH_COMPAT
5069  redirect_more:
5070 #endif
5071                 if (need_to_remember(sv, fd)) {
5072                         /* Copy old descriptor */
5073                         i = fcntl(fd, F_DUPFD, 10);
5074 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5075  * are closed in popredir() in the child, preventing them from leaking
5076  * into child. (popredir() also cleans up the mess in case of failures)
5077  */
5078                         if (i == -1) {
5079                                 i = errno;
5080                                 if (i != EBADF) {
5081                                         /* Strange error (e.g. "too many files" EMFILE?) */
5082                                         if (newfd >= 0)
5083                                                 close(newfd);
5084                                         errno = i;
5085                                         ash_msg_and_raise_error("%d: %m", fd);
5086                                         /* NOTREACHED */
5087                                 }
5088                                 /* EBADF: it is not open - good, remember to close it */
5089  remember_to_close:
5090                                 i = CLOSED;
5091                         } else { /* fd is open, save its copy */
5092                                 /* "exec fd>&-" should not close fds
5093                                  * which point to script file(s).
5094                                  * Force them to be restored afterwards */
5095                                 if (is_hidden_fd(sv, fd))
5096                                         i |= COPYFD_RESTORE;
5097                         }
5098                         if (fd == 2)
5099                                 copied_fd2 = i;
5100                         sv->two_fd[sv_pos].orig = fd;
5101                         sv->two_fd[sv_pos].copy = i;
5102                         sv_pos++;
5103                 }
5104                 if (newfd < 0) {
5105                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5106                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5107                                 close(fd);
5108                         } else {
5109                                 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5110                         }
5111                 } else if (fd != newfd) { /* move newfd to fd */
5112                         copyfd(newfd, fd | COPYFD_EXACT);
5113 #if ENABLE_ASH_BASH_COMPAT
5114                         if (!(redir->nfile.type == NTO2 && fd == 2))
5115 #endif
5116                                 close(newfd);
5117                 }
5118 #if ENABLE_ASH_BASH_COMPAT
5119                 if (redir->nfile.type == NTO2 && fd == 1) {
5120                         /* We already redirected it to fd 1, now copy it to 2 */
5121                         newfd = 1;
5122                         fd = 2;
5123                         goto redirect_more;
5124                 }
5125 #endif
5126         } while ((redir = redir->nfile.next) != NULL);
5127
5128         INT_ON;
5129         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5130                 preverrout_fd = copied_fd2;
5131 }
5132
5133 /*
5134  * Undo the effects of the last redirection.
5135  */
5136 static void
5137 popredir(int drop, int restore)
5138 {
5139         struct redirtab *rp;
5140         int i;
5141
5142         if (--g_nullredirs >= 0)
5143                 return;
5144         INT_OFF;
5145         rp = redirlist;
5146         for (i = 0; i < rp->pair_count; i++) {
5147                 int fd = rp->two_fd[i].orig;
5148                 int copy = rp->two_fd[i].copy;
5149                 if (copy == CLOSED) {
5150                         if (!drop)
5151                                 close(fd);
5152                         continue;
5153                 }
5154                 if (copy != EMPTY) {
5155                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5156                                 copy &= ~COPYFD_RESTORE;
5157                                 /*close(fd);*/
5158                                 copyfd(copy, fd | COPYFD_EXACT);
5159                         }
5160                         close(copy);
5161                 }
5162         }
5163         redirlist = rp->next;
5164         g_nullredirs = rp->nullredirs;
5165         free(rp);
5166         INT_ON;
5167 }
5168
5169 /*
5170  * Undo all redirections.  Called on error or interrupt.
5171  */
5172
5173 /*
5174  * Discard all saved file descriptors.
5175  */
5176 static void
5177 clearredir(int drop)
5178 {
5179         for (;;) {
5180                 g_nullredirs = 0;
5181                 if (!redirlist)
5182                         break;
5183                 popredir(drop, /*restore:*/ 0);
5184         }
5185 }
5186
5187 static int
5188 redirectsafe(union node *redir, int flags)
5189 {
5190         int err;
5191         volatile int saveint;
5192         struct jmploc *volatile savehandler = exception_handler;
5193         struct jmploc jmploc;
5194
5195         SAVE_INT(saveint);
5196         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5197         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5198         if (!err) {
5199                 exception_handler = &jmploc;
5200                 redirect(redir, flags);
5201         }
5202         exception_handler = savehandler;
5203         if (err && exception_type != EXERROR)
5204                 longjmp(exception_handler->loc, 1);
5205         RESTORE_INT(saveint);
5206         return err;
5207 }
5208
5209
5210 /* ============ Routines to expand arguments to commands
5211  *
5212  * We have to deal with backquotes, shell variables, and file metacharacters.
5213  */
5214
5215 #if ENABLE_ASH_MATH_SUPPORT_64
5216 typedef int64_t arith_t;
5217 #define arith_t_type long long
5218 #else
5219 typedef long arith_t;
5220 #define arith_t_type long
5221 #endif
5222
5223 #if ENABLE_ASH_MATH_SUPPORT
5224 static arith_t dash_arith(const char *);
5225 static arith_t arith(const char *expr, int *perrcode);
5226 #endif
5227
5228 /*
5229  * expandarg flags
5230  */
5231 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5232 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5233 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5234 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5235 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5236 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
5237 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5238 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5239 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
5240 /*
5241  * _rmescape() flags
5242  */
5243 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5244 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5245 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
5246 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5247 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5248
5249 /*
5250  * Structure specifying which parts of the string should be searched
5251  * for IFS characters.
5252  */
5253 struct ifsregion {
5254         struct ifsregion *next; /* next region in list */
5255         int begoff;             /* offset of start of region */
5256         int endoff;             /* offset of end of region */
5257         int nulonly;            /* search for nul bytes only */
5258 };
5259
5260 struct arglist {
5261         struct strlist *list;
5262         struct strlist **lastp;
5263 };
5264
5265 /* output of current string */
5266 static char *expdest;
5267 /* list of back quote expressions */
5268 static struct nodelist *argbackq;
5269 /* first struct in list of ifs regions */
5270 static struct ifsregion ifsfirst;
5271 /* last struct in list */
5272 static struct ifsregion *ifslastp;
5273 /* holds expanded arg list */
5274 static struct arglist exparg;
5275
5276 /*
5277  * Our own itoa().
5278  */
5279 static int
5280 cvtnum(arith_t num)
5281 {
5282         int len;
5283
5284         expdest = makestrspace(32, expdest);
5285 #if ENABLE_ASH_MATH_SUPPORT_64
5286         len = fmtstr(expdest, 32, "%lld", (long long) num);
5287 #else
5288         len = fmtstr(expdest, 32, "%ld", num);
5289 #endif
5290         STADJUST(len, expdest);
5291         return len;
5292 }
5293
5294 static size_t
5295 esclen(const char *start, const char *p)
5296 {
5297         size_t esc = 0;
5298
5299         while (p > start && *--p == CTLESC) {
5300                 esc++;
5301         }
5302         return esc;
5303 }
5304
5305 /*
5306  * Remove any CTLESC characters from a string.
5307  */
5308 static char *
5309 _rmescapes(char *str, int flag)
5310 {
5311         static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5312
5313         char *p, *q, *r;
5314         unsigned inquotes;
5315         int notescaped;
5316         int globbing;
5317
5318         p = strpbrk(str, qchars);
5319         if (!p) {
5320                 return str;
5321         }
5322         q = p;
5323         r = str;
5324         if (flag & RMESCAPE_ALLOC) {
5325                 size_t len = p - str;
5326                 size_t fulllen = len + strlen(p) + 1;
5327
5328                 if (flag & RMESCAPE_GROW) {
5329                         r = makestrspace(fulllen, expdest);
5330                 } else if (flag & RMESCAPE_HEAP) {
5331                         r = ckmalloc(fulllen);
5332                 } else {
5333                         r = stalloc(fulllen);
5334                 }
5335                 q = r;
5336                 if (len > 0) {
5337                         q = (char *)memcpy(q, str, len) + len;
5338                 }
5339         }
5340         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5341         globbing = flag & RMESCAPE_GLOB;
5342         notescaped = globbing;
5343         while (*p) {
5344                 if (*p == CTLQUOTEMARK) {
5345                         inquotes = ~inquotes;
5346                         p++;
5347                         notescaped = globbing;
5348                         continue;
5349                 }
5350                 if (*p == '\\') {
5351                         /* naked back slash */
5352                         notescaped = 0;
5353                         goto copy;
5354                 }
5355                 if (*p == CTLESC) {
5356                         p++;
5357                         if (notescaped && inquotes && *p != '/') {
5358                                 *q++ = '\\';
5359                         }
5360                 }
5361                 notescaped = globbing;
5362  copy:
5363                 *q++ = *p++;
5364         }
5365         *q = '\0';
5366         if (flag & RMESCAPE_GROW) {
5367                 expdest = r;
5368                 STADJUST(q - r + 1, expdest);
5369         }
5370         return r;
5371 }
5372 #define rmescapes(p) _rmescapes((p), 0)
5373
5374 #define pmatch(a, b) !fnmatch((a), (b), 0)
5375
5376 /*
5377  * Prepare a pattern for a expmeta (internal glob(3)) call.
5378  *
5379  * Returns an stalloced string.
5380  */
5381 static char *
5382 preglob(const char *pattern, int quoted, int flag)
5383 {
5384         flag |= RMESCAPE_GLOB;
5385         if (quoted) {
5386                 flag |= RMESCAPE_QUOTED;
5387         }
5388         return _rmescapes((char *)pattern, flag);
5389 }
5390
5391 /*
5392  * Put a string on the stack.
5393  */
5394 static void
5395 memtodest(const char *p, size_t len, int syntax, int quotes)
5396 {
5397         char *q = expdest;
5398
5399         q = makestrspace(len * 2, q);
5400
5401         while (len--) {
5402                 int c = signed_char2int(*p++);
5403                 if (!c)
5404                         continue;
5405                 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5406                         USTPUTC(CTLESC, q);
5407                 USTPUTC(c, q);
5408         }
5409
5410         expdest = q;
5411 }
5412
5413 static void
5414 strtodest(const char *p, int syntax, int quotes)
5415 {
5416         memtodest(p, strlen(p), syntax, quotes);
5417 }
5418
5419 /*
5420  * Record the fact that we have to scan this region of the
5421  * string for IFS characters.
5422  */
5423 static void
5424 recordregion(int start, int end, int nulonly)
5425 {
5426         struct ifsregion *ifsp;
5427
5428         if (ifslastp == NULL) {
5429                 ifsp = &ifsfirst;
5430         } else {
5431                 INT_OFF;
5432                 ifsp = ckzalloc(sizeof(*ifsp));
5433                 /*ifsp->next = NULL; - ckzalloc did it */
5434                 ifslastp->next = ifsp;
5435                 INT_ON;
5436         }
5437         ifslastp = ifsp;
5438         ifslastp->begoff = start;
5439         ifslastp->endoff = end;
5440         ifslastp->nulonly = nulonly;
5441 }
5442
5443 static void
5444 removerecordregions(int endoff)
5445 {
5446         if (ifslastp == NULL)
5447                 return;
5448
5449         if (ifsfirst.endoff > endoff) {
5450                 while (ifsfirst.next != NULL) {
5451                         struct ifsregion *ifsp;
5452                         INT_OFF;
5453                         ifsp = ifsfirst.next->next;
5454                         free(ifsfirst.next);
5455                         ifsfirst.next = ifsp;
5456                         INT_ON;
5457                 }
5458                 if (ifsfirst.begoff > endoff)
5459                         ifslastp = NULL;
5460                 else {
5461                         ifslastp = &ifsfirst;
5462                         ifsfirst.endoff = endoff;
5463                 }
5464                 return;
5465         }
5466
5467         ifslastp = &ifsfirst;
5468         while (ifslastp->next && ifslastp->next->begoff < endoff)
5469                 ifslastp=ifslastp->next;
5470         while (ifslastp->next != NULL) {
5471                 struct ifsregion *ifsp;
5472                 INT_OFF;
5473                 ifsp = ifslastp->next->next;
5474                 free(ifslastp->next);
5475                 ifslastp->next = ifsp;
5476                 INT_ON;
5477         }
5478         if (ifslastp->endoff > endoff)
5479                 ifslastp->endoff = endoff;
5480 }
5481
5482 static char *
5483 exptilde(char *startp, char *p, int flag)
5484 {
5485         char c;
5486         char *name;
5487         struct passwd *pw;
5488         const char *home;
5489         int quotes = flag & (EXP_FULL | EXP_CASE);
5490         int startloc;
5491
5492         name = p + 1;
5493
5494         while ((c = *++p) != '\0') {
5495                 switch (c) {
5496                 case CTLESC:
5497                         return startp;
5498                 case CTLQUOTEMARK:
5499                         return startp;
5500                 case ':':
5501                         if (flag & EXP_VARTILDE)
5502                                 goto done;
5503                         break;
5504                 case '/':
5505                 case CTLENDVAR:
5506                         goto done;
5507                 }
5508         }
5509  done:
5510         *p = '\0';
5511         if (*name == '\0') {
5512                 home = lookupvar(homestr);
5513         } else {
5514                 pw = getpwnam(name);
5515                 if (pw == NULL)
5516                         goto lose;
5517                 home = pw->pw_dir;
5518         }
5519         if (!home || !*home)
5520                 goto lose;
5521         *p = c;
5522         startloc = expdest - (char *)stackblock();
5523         strtodest(home, SQSYNTAX, quotes);
5524         recordregion(startloc, expdest - (char *)stackblock(), 0);
5525         return p;
5526  lose:
5527         *p = c;
5528         return startp;
5529 }
5530
5531 /*
5532  * Execute a command inside back quotes.  If it's a builtin command, we
5533  * want to save its output in a block obtained from malloc.  Otherwise
5534  * we fork off a subprocess and get the output of the command via a pipe.
5535  * Should be called with interrupts off.
5536  */
5537 struct backcmd {                /* result of evalbackcmd */
5538         int fd;                 /* file descriptor to read from */
5539         int nleft;              /* number of chars in buffer */
5540         char *buf;              /* buffer */
5541         struct job *jp;         /* job structure for command */
5542 };
5543
5544 /* These forward decls are needed to use "eval" code for backticks handling: */
5545 static uint8_t back_exitstatus; /* exit status of backquoted command */
5546 #define EV_EXIT 01              /* exit after evaluating tree */
5547 static void evaltree(union node *, int);
5548
5549 static void
5550 evalbackcmd(union node *n, struct backcmd *result)
5551 {
5552         int saveherefd;
5553
5554         result->fd = -1;
5555         result->buf = NULL;
5556         result->nleft = 0;
5557         result->jp = NULL;
5558         if (n == NULL)
5559                 goto out;
5560
5561         saveherefd = herefd;
5562         herefd = -1;
5563
5564         {
5565                 int pip[2];
5566                 struct job *jp;
5567
5568                 if (pipe(pip) < 0)
5569                         ash_msg_and_raise_error("pipe call failed");
5570                 jp = makejob(/*n,*/ 1);
5571                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5572                         FORCE_INT_ON;
5573                         close(pip[0]);
5574                         if (pip[1] != 1) {
5575                                 /*close(1);*/
5576                                 copyfd(pip[1], 1 | COPYFD_EXACT);
5577                                 close(pip[1]);
5578                         }
5579                         eflag = 0;
5580                         evaltree(n, EV_EXIT); /* actually evaltreenr... */
5581                         /* NOTREACHED */
5582                 }
5583                 close(pip[1]);
5584                 result->fd = pip[0];
5585                 result->jp = jp;
5586         }
5587         herefd = saveherefd;
5588  out:
5589         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5590                 result->fd, result->buf, result->nleft, result->jp));
5591 }
5592
5593 /*
5594  * Expand stuff in backwards quotes.
5595  */
5596 static void
5597 expbackq(union node *cmd, int quoted, int quotes)
5598 {
5599         struct backcmd in;
5600         int i;
5601         char buf[128];
5602         char *p;
5603         char *dest;
5604         int startloc;
5605         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5606         struct stackmark smark;
5607
5608         INT_OFF;
5609         setstackmark(&smark);
5610         dest = expdest;
5611         startloc = dest - (char *)stackblock();
5612         grabstackstr(dest);
5613         evalbackcmd(cmd, &in);
5614         popstackmark(&smark);
5615
5616         p = in.buf;
5617         i = in.nleft;
5618         if (i == 0)
5619                 goto read;
5620         for (;;) {
5621                 memtodest(p, i, syntax, quotes);
5622  read:
5623                 if (in.fd < 0)
5624                         break;
5625                 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5626                 TRACE(("expbackq: read returns %d\n", i));
5627                 if (i <= 0)
5628                         break;
5629                 p = buf;
5630         }
5631
5632         free(in.buf);
5633         if (in.fd >= 0) {
5634                 close(in.fd);
5635                 back_exitstatus = waitforjob(in.jp);
5636         }
5637         INT_ON;
5638
5639         /* Eat all trailing newlines */
5640         dest = expdest;
5641         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5642                 STUNPUTC(dest);
5643         expdest = dest;
5644
5645         if (quoted == 0)
5646                 recordregion(startloc, dest - (char *)stackblock(), 0);
5647         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5648                 (dest - (char *)stackblock()) - startloc,
5649                 (dest - (char *)stackblock()) - startloc,
5650                 stackblock() + startloc));
5651 }
5652
5653 #if ENABLE_ASH_MATH_SUPPORT
5654 /*
5655  * Expand arithmetic expression.  Backup to start of expression,
5656  * evaluate, place result in (backed up) result, adjust string position.
5657  */
5658 static void
5659 expari(int quotes)
5660 {
5661         char *p, *start;
5662         int begoff;
5663         int flag;
5664         int len;
5665
5666         /* ifsfree(); */
5667
5668         /*
5669          * This routine is slightly over-complicated for
5670          * efficiency.  Next we scan backwards looking for the
5671          * start of arithmetic.
5672          */
5673         start = stackblock();
5674         p = expdest - 1;
5675         *p = '\0';
5676         p--;
5677         do {
5678                 int esc;
5679
5680                 while (*p != CTLARI) {
5681                         p--;
5682 #if DEBUG
5683                         if (p < start) {
5684                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5685                         }
5686 #endif
5687                 }
5688
5689                 esc = esclen(start, p);
5690                 if (!(esc % 2)) {
5691                         break;
5692                 }
5693
5694                 p -= esc + 1;
5695         } while (1);
5696
5697         begoff = p - start;
5698
5699         removerecordregions(begoff);
5700
5701         flag = p[1];
5702
5703         expdest = p;
5704
5705         if (quotes)
5706                 rmescapes(p + 2);
5707
5708         len = cvtnum(dash_arith(p + 2));
5709
5710         if (flag != '"')
5711                 recordregion(begoff, begoff + len, 0);
5712 }
5713 #endif
5714
5715 /* argstr needs it */
5716 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5717
5718 /*
5719  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
5720  * characters to allow for further processing.  Otherwise treat
5721  * $@ like $* since no splitting will be performed.
5722  *
5723  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5724  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5725  * for correct expansion of "B=$A" word.
5726  */
5727 static void
5728 argstr(char *p, int flag, struct strlist *var_str_list)
5729 {
5730         static const char spclchars[] ALIGN1 = {
5731                 '=',
5732                 ':',
5733                 CTLQUOTEMARK,
5734                 CTLENDVAR,
5735                 CTLESC,
5736                 CTLVAR,
5737                 CTLBACKQ,
5738                 CTLBACKQ | CTLQUOTE,
5739 #if ENABLE_ASH_MATH_SUPPORT
5740                 CTLENDARI,
5741 #endif
5742                 0
5743         };
5744         const char *reject = spclchars;
5745         int c;
5746         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
5747         int breakall = flag & EXP_WORD;
5748         int inquotes;
5749         size_t length;
5750         int startloc;
5751
5752         if (!(flag & EXP_VARTILDE)) {
5753                 reject += 2;
5754         } else if (flag & EXP_VARTILDE2) {
5755                 reject++;
5756         }
5757         inquotes = 0;
5758         length = 0;
5759         if (flag & EXP_TILDE) {
5760                 char *q;
5761
5762                 flag &= ~EXP_TILDE;
5763  tilde:
5764                 q = p;
5765                 if (*q == CTLESC && (flag & EXP_QWORD))
5766                         q++;
5767                 if (*q == '~')
5768                         p = exptilde(p, q, flag);
5769         }
5770  start:
5771         startloc = expdest - (char *)stackblock();
5772         for (;;) {
5773                 length += strcspn(p + length, reject);
5774                 c = p[length];
5775                 if (c && (!(c & 0x80)
5776 #if ENABLE_ASH_MATH_SUPPORT
5777                                         || c == CTLENDARI
5778 #endif
5779                    )) {
5780                         /* c == '=' || c == ':' || c == CTLENDARI */
5781                         length++;
5782                 }
5783                 if (length > 0) {
5784                         int newloc;
5785                         expdest = stack_nputstr(p, length, expdest);
5786                         newloc = expdest - (char *)stackblock();
5787                         if (breakall && !inquotes && newloc > startloc) {
5788                                 recordregion(startloc, newloc, 0);
5789                         }
5790                         startloc = newloc;
5791                 }
5792                 p += length + 1;
5793                 length = 0;
5794
5795                 switch (c) {
5796                 case '\0':
5797                         goto breakloop;
5798                 case '=':
5799                         if (flag & EXP_VARTILDE2) {
5800                                 p--;
5801                                 continue;
5802                         }
5803                         flag |= EXP_VARTILDE2;
5804                         reject++;
5805                         /* fall through */
5806                 case ':':
5807                         /*
5808                          * sort of a hack - expand tildes in variable
5809                          * assignments (after the first '=' and after ':'s).
5810                          */
5811                         if (*--p == '~') {
5812                                 goto tilde;
5813                         }
5814                         continue;
5815                 }
5816
5817                 switch (c) {
5818                 case CTLENDVAR: /* ??? */
5819                         goto breakloop;
5820                 case CTLQUOTEMARK:
5821                         /* "$@" syntax adherence hack */
5822                         if (
5823                                 !inquotes &&
5824                                 !memcmp(p, dolatstr, 4) &&
5825                                 (p[4] == CTLQUOTEMARK || (
5826                                         p[4] == CTLENDVAR &&
5827                                         p[5] == CTLQUOTEMARK
5828                                 ))
5829                         ) {
5830                                 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5831                                 goto start;
5832                         }
5833                         inquotes = !inquotes;
5834  addquote:
5835                         if (quotes) {
5836                                 p--;
5837                                 length++;
5838                                 startloc++;
5839                         }
5840                         break;
5841                 case CTLESC:
5842                         startloc++;
5843                         length++;
5844                         goto addquote;
5845                 case CTLVAR:
5846                         p = evalvar(p, flag, var_str_list);
5847                         goto start;
5848                 case CTLBACKQ:
5849                         c = 0;
5850                 case CTLBACKQ|CTLQUOTE:
5851                         expbackq(argbackq->n, c, quotes);
5852                         argbackq = argbackq->next;
5853                         goto start;
5854 #if ENABLE_ASH_MATH_SUPPORT
5855                 case CTLENDARI:
5856                         p--;
5857                         expari(quotes);
5858                         goto start;
5859 #endif
5860                 }
5861         }
5862  breakloop:
5863         ;
5864 }
5865
5866 static char *
5867 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5868         int zero)
5869 {
5870 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5871 // as part of a larger change when he added support for ${var/a/b}.
5872 // However, it broke # and % operators:
5873 //
5874 //var=ababcdcd
5875 //                 ok       bad
5876 //echo ${var#ab}   abcdcd   abcdcd
5877 //echo ${var##ab}  abcdcd   abcdcd
5878 //echo ${var#a*b}  abcdcd   ababcdcd  (!)
5879 //echo ${var##a*b} cdcd     cdcd
5880 //echo ${var#?}    babcdcd  ababcdcd  (!)
5881 //echo ${var##?}   babcdcd  babcdcd
5882 //echo ${var#*}    ababcdcd babcdcd   (!)
5883 //echo ${var##*}
5884 //echo ${var%cd}   ababcd   ababcd
5885 //echo ${var%%cd}  ababcd   abab      (!)
5886 //echo ${var%c*d}  ababcd   ababcd
5887 //echo ${var%%c*d} abab     ababcdcd  (!)
5888 //echo ${var%?}    ababcdc  ababcdc
5889 //echo ${var%%?}   ababcdc  ababcdcd  (!)
5890 //echo ${var%*}    ababcdcd ababcdcd
5891 //echo ${var%%*}
5892 //
5893 // Commenting it back out helped. Remove it completely if it really
5894 // is not needed.
5895
5896         char *loc, *loc2; //, *full;
5897         char c;
5898
5899         loc = startp;
5900         loc2 = rmesc;
5901         do {
5902                 int match; // = strlen(str);
5903                 const char *s = loc2;
5904
5905                 c = *loc2;
5906                 if (zero) {
5907                         *loc2 = '\0';
5908                         s = rmesc;
5909                 }
5910                 match = pmatch(str, s); // this line was deleted
5911
5912 //              // chop off end if its '*'
5913 //              full = strrchr(str, '*');
5914 //              if (full && full != str)
5915 //                      match--;
5916 //
5917 //              // If str starts with '*' replace with s.
5918 //              if ((*str == '*') && strlen(s) >= match) {
5919 //                      full = xstrdup(s);
5920 //                      strncpy(full+strlen(s)-match+1, str+1, match-1);
5921 //              } else
5922 //                      full = xstrndup(str, match);
5923 //              match = strncmp(s, full, strlen(full));
5924 //              free(full);
5925 //
5926                 *loc2 = c;
5927                 if (match) // if (!match)
5928                         return loc;
5929                 if (quotes && *loc == CTLESC)
5930                         loc++;
5931                 loc++;
5932                 loc2++;
5933         } while (c);
5934         return 0;
5935 }
5936
5937 static char *
5938 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5939         int zero)
5940 {
5941         int esc = 0;
5942         char *loc;
5943         char *loc2;
5944
5945         for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5946                 int match;
5947                 char c = *loc2;
5948                 const char *s = loc2;
5949                 if (zero) {
5950                         *loc2 = '\0';
5951                         s = rmesc;
5952                 }
5953                 match = pmatch(str, s);
5954                 *loc2 = c;
5955                 if (match)
5956                         return loc;
5957                 loc--;
5958                 if (quotes) {
5959                         if (--esc < 0) {
5960                                 esc = esclen(startp, loc);
5961                         }
5962                         if (esc % 2) {
5963                                 esc--;
5964                                 loc--;
5965                         }
5966                 }
5967         }
5968         return 0;
5969 }
5970
5971 static void varunset(const char *, const char *, const char *, int) NORETURN;
5972 static void
5973 varunset(const char *end, const char *var, const char *umsg, int varflags)
5974 {
5975         const char *msg;
5976         const char *tail;
5977
5978         tail = nullstr;
5979         msg = "parameter not set";
5980         if (umsg) {
5981                 if (*end == CTLENDVAR) {
5982                         if (varflags & VSNUL)
5983                                 tail = " or null";
5984                 } else {
5985                         msg = umsg;
5986                 }
5987         }
5988         ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5989 }
5990
5991 #if ENABLE_ASH_BASH_COMPAT
5992 static char *
5993 parse_sub_pattern(char *arg, int inquotes)
5994 {
5995         char *idx, *repl = NULL;
5996         unsigned char c;
5997
5998         idx = arg;
5999         while (1) {
6000                 c = *arg;
6001                 if (!c)
6002                         break;
6003                 if (c == '/') {
6004                         /* Only the first '/' seen is our separator */
6005                         if (!repl) {
6006                                 repl = idx + 1;
6007                                 c = '\0';
6008                         }
6009                 }
6010                 *idx++ = c;
6011                 if (!inquotes && c == '\\' && arg[1] == '\\')
6012                         arg++; /* skip both \\, not just first one */
6013                 arg++;
6014         }
6015         *idx = c; /* NUL */
6016
6017         return repl;
6018 }
6019 #endif /* ENABLE_ASH_BASH_COMPAT */
6020
6021 static const char *
6022 subevalvar(char *p, char *str, int strloc, int subtype,
6023                 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6024 {
6025         struct nodelist *saveargbackq = argbackq;
6026         char *startp;
6027         char *loc;
6028         char *rmesc, *rmescend;
6029         USE_ASH_BASH_COMPAT(char *repl = NULL;)
6030         USE_ASH_BASH_COMPAT(char null = '\0';)
6031         USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6032         int saveherefd = herefd;
6033         int amount, workloc, resetloc;
6034         int zero;
6035         char *(*scan)(char*, char*, char*, char*, int, int);
6036
6037         herefd = -1;
6038         argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6039                         var_str_list);
6040         STPUTC('\0', expdest);
6041         herefd = saveherefd;
6042         argbackq = saveargbackq;
6043         startp = (char *)stackblock() + startloc;
6044
6045         switch (subtype) {
6046         case VSASSIGN:
6047                 setvar(str, startp, 0);
6048                 amount = startp - expdest;
6049                 STADJUST(amount, expdest);
6050                 return startp;
6051
6052 #if ENABLE_ASH_BASH_COMPAT
6053         case VSSUBSTR:
6054                 loc = str = stackblock() + strloc;
6055 // TODO: number() instead? It does error checking...
6056                 pos = atoi(loc);
6057                 len = str - startp - 1;
6058
6059                 /* *loc != '\0', guaranteed by parser */
6060                 if (quotes) {
6061                         char *ptr;
6062
6063                         /* We must adjust the length by the number of escapes we find. */
6064                         for (ptr = startp; ptr < (str - 1); ptr++) {
6065                                 if (*ptr == CTLESC) {
6066                                         len--;
6067                                         ptr++;
6068                                 }
6069                         }
6070                 }
6071                 orig_len = len;
6072
6073                 if (*loc++ == ':') {
6074 // TODO: number() instead? It does error checking...
6075                         len = atoi(loc);
6076                 } else {
6077                         len = orig_len;
6078                         while (*loc && *loc != ':')
6079                                 loc++;
6080                         if (*loc++ == ':')
6081 // TODO: number() instead? It does error checking...
6082                                 len = atoi(loc);
6083                 }
6084                 if (pos >= orig_len) {
6085                         pos = 0;
6086                         len = 0;
6087                 }
6088                 if (len > (orig_len - pos))
6089                         len = orig_len - pos;
6090
6091                 for (str = startp; pos; str++, pos--) {
6092                         if (quotes && *str == CTLESC)
6093                                 str++;
6094                 }
6095                 for (loc = startp; len; len--) {
6096                         if (quotes && *str == CTLESC)
6097                                 *loc++ = *str++;
6098                         *loc++ = *str++;
6099                 }
6100                 *loc = '\0';
6101                 amount = loc - expdest;
6102                 STADJUST(amount, expdest);
6103                 return loc;
6104 #endif
6105
6106         case VSQUESTION:
6107                 varunset(p, str, startp, varflags);
6108                 /* NOTREACHED */
6109         }
6110         resetloc = expdest - (char *)stackblock();
6111
6112         /* We'll comeback here if we grow the stack while handling
6113          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6114          * stack will need rebasing, and we'll need to remove our work
6115          * areas each time
6116          */
6117  USE_ASH_BASH_COMPAT(restart:)
6118
6119         amount = expdest - ((char *)stackblock() + resetloc);
6120         STADJUST(-amount, expdest);
6121         startp = (char *)stackblock() + startloc;
6122
6123         rmesc = startp;
6124         rmescend = (char *)stackblock() + strloc;
6125         if (quotes) {
6126                 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6127                 if (rmesc != startp) {
6128                         rmescend = expdest;
6129                         startp = (char *)stackblock() + startloc;
6130                 }
6131         }
6132         rmescend--;
6133         str = (char *)stackblock() + strloc;
6134         preglob(str, varflags & VSQUOTE, 0);
6135         workloc = expdest - (char *)stackblock();
6136
6137 #if ENABLE_ASH_BASH_COMPAT
6138         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6139                 char *idx, *end, *restart_detect;
6140
6141                 if (!repl) {
6142                         repl = parse_sub_pattern(str, varflags & VSQUOTE);
6143                         if (!repl)
6144                                 repl = &null;
6145                 }
6146
6147                 /* If there's no pattern to match, return the expansion unmolested */
6148                 if (*str == '\0')
6149                         return 0;
6150
6151                 len = 0;
6152                 idx = startp;
6153                 end = str - 1;
6154                 while (idx < end) {
6155                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6156                         if (!loc) {
6157                                 /* No match, advance */
6158                                 restart_detect = stackblock();
6159                                 STPUTC(*idx, expdest);
6160                                 if (quotes && *idx == CTLESC) {
6161                                         idx++;
6162                                         len++;
6163                                         STPUTC(*idx, expdest);
6164                                 }
6165                                 if (stackblock() != restart_detect)
6166                                         goto restart;
6167                                 idx++;
6168                                 len++;
6169                                 rmesc++;
6170                                 continue;
6171                         }
6172
6173                         if (subtype == VSREPLACEALL) {
6174                                 while (idx < loc) {
6175                                         if (quotes && *idx == CTLESC)
6176                                                 idx++;
6177                                         idx++;
6178                                         rmesc++;
6179                                 }
6180                         } else {
6181                                 idx = loc;
6182                         }
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         struct jmploc *volatile savehandler = exception_handler;
7984         struct jmploc jmploc;
7985         int checkexit = 0;
7986         void (*evalfn)(union node *, int);
7987         int status;
7988
7989         if (n == NULL) {
7990                 TRACE(("evaltree(NULL) called\n"));
7991                 goto out1;
7992         }
7993         TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7994                         getpid(), n, n->type, flags));
7995
7996         exception_handler = &jmploc;
7997         {
7998                 int err = setjmp(jmploc.loc);
7999                 if (err) {
8000                         /* if it was a signal, check for trap handlers */
8001                         if (exception_type == EXSIG)
8002                                 goto out;
8003                         /* continue on the way out */
8004                         exception_handler = savehandler;
8005                         longjmp(exception_handler->loc, err);
8006                 }
8007         }
8008
8009         switch (n->type) {
8010         default:
8011 #if DEBUG
8012                 out1fmt("Node type = %d\n", n->type);
8013                 fflush(stdout);
8014                 break;
8015 #endif
8016         case NNOT:
8017                 evaltree(n->nnot.com, EV_TESTED);
8018                 status = !exitstatus;
8019                 goto setstatus;
8020         case NREDIR:
8021                 expredir(n->nredir.redirect);
8022                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8023                 if (!status) {
8024                         evaltree(n->nredir.n, flags & EV_TESTED);
8025                         status = exitstatus;
8026                 }
8027                 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8028                 goto setstatus;
8029         case NCMD:
8030                 evalfn = evalcommand;
8031  checkexit:
8032                 if (eflag && !(flags & EV_TESTED))
8033                         checkexit = ~0;
8034                 goto calleval;
8035         case NFOR:
8036                 evalfn = evalfor;
8037                 goto calleval;
8038         case NWHILE:
8039         case NUNTIL:
8040                 evalfn = evalloop;
8041                 goto calleval;
8042         case NSUBSHELL:
8043         case NBACKGND:
8044                 evalfn = evalsubshell;
8045                 goto calleval;
8046         case NPIPE:
8047                 evalfn = evalpipe;
8048                 goto checkexit;
8049         case NCASE:
8050                 evalfn = evalcase;
8051                 goto calleval;
8052         case NAND:
8053         case NOR:
8054         case NSEMI: {
8055
8056 #if NAND + 1 != NOR
8057 #error NAND + 1 != NOR
8058 #endif
8059 #if NOR + 1 != NSEMI
8060 #error NOR + 1 != NSEMI
8061 #endif
8062                 unsigned is_or = n->type - NAND;
8063                 evaltree(
8064                         n->nbinary.ch1,
8065                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8066                 );
8067                 if (!exitstatus == is_or)
8068                         break;
8069                 if (!evalskip) {
8070                         n = n->nbinary.ch2;
8071  evaln:
8072                         evalfn = evaltree;
8073  calleval:
8074                         evalfn(n, flags);
8075                         break;
8076                 }
8077                 break;
8078         }
8079         case NIF:
8080                 evaltree(n->nif.test, EV_TESTED);
8081                 if (evalskip)
8082                         break;
8083                 if (exitstatus == 0) {
8084                         n = n->nif.ifpart;
8085                         goto evaln;
8086                 } else if (n->nif.elsepart) {
8087                         n = n->nif.elsepart;
8088                         goto evaln;
8089                 }
8090                 goto success;
8091         case NDEFUN:
8092                 defun(n->narg.text, n->narg.next);
8093  success:
8094                 status = 0;
8095  setstatus:
8096                 exitstatus = status;
8097                 break;
8098         }
8099
8100  out:
8101         exception_handler = savehandler;
8102  out1:
8103         if (checkexit & exitstatus)
8104                 evalskip |= SKIPEVAL;
8105         else if (pendingsig && dotrap())
8106                 goto exexit;
8107
8108         if (flags & EV_EXIT) {
8109  exexit:
8110                 raise_exception(EXEXIT);
8111         }
8112 }
8113
8114 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8115 static
8116 #endif
8117 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8118
8119 static void
8120 evalloop(union node *n, int flags)
8121 {
8122         int status;
8123
8124         loopnest++;
8125         status = 0;
8126         flags &= EV_TESTED;
8127         for (;;) {
8128                 int i;
8129
8130                 evaltree(n->nbinary.ch1, EV_TESTED);
8131                 if (evalskip) {
8132  skipping:
8133                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8134                                 evalskip = 0;
8135                                 continue;
8136                         }
8137                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8138                                 evalskip = 0;
8139                         break;
8140                 }
8141                 i = exitstatus;
8142                 if (n->type != NWHILE)
8143                         i = !i;
8144                 if (i != 0)
8145                         break;
8146                 evaltree(n->nbinary.ch2, flags);
8147                 status = exitstatus;
8148                 if (evalskip)
8149                         goto skipping;
8150         }
8151         loopnest--;
8152         exitstatus = status;
8153 }
8154
8155 static void
8156 evalfor(union node *n, int flags)
8157 {
8158         struct arglist arglist;
8159         union node *argp;
8160         struct strlist *sp;
8161         struct stackmark smark;
8162
8163         setstackmark(&smark);
8164         arglist.list = NULL;
8165         arglist.lastp = &arglist.list;
8166         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8167                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8168                 /* XXX */
8169                 if (evalskip)
8170                         goto out;
8171         }
8172         *arglist.lastp = NULL;
8173
8174         exitstatus = 0;
8175         loopnest++;
8176         flags &= EV_TESTED;
8177         for (sp = arglist.list; sp; sp = sp->next) {
8178                 setvar(n->nfor.var, sp->text, 0);
8179                 evaltree(n->nfor.body, flags);
8180                 if (evalskip) {
8181                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8182                                 evalskip = 0;
8183                                 continue;
8184                         }
8185                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8186                                 evalskip = 0;
8187                         break;
8188                 }
8189         }
8190         loopnest--;
8191  out:
8192         popstackmark(&smark);
8193 }
8194
8195 static void
8196 evalcase(union node *n, int flags)
8197 {
8198         union node *cp;
8199         union node *patp;
8200         struct arglist arglist;
8201         struct stackmark smark;
8202
8203         setstackmark(&smark);
8204         arglist.list = NULL;
8205         arglist.lastp = &arglist.list;
8206         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8207         exitstatus = 0;
8208         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8209                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8210                         if (casematch(patp, arglist.list->text)) {
8211                                 if (evalskip == 0) {
8212                                         evaltree(cp->nclist.body, flags);
8213                                 }
8214                                 goto out;
8215                         }
8216                 }
8217         }
8218  out:
8219         popstackmark(&smark);
8220 }
8221
8222 /*
8223  * Kick off a subshell to evaluate a tree.
8224  */
8225 static void
8226 evalsubshell(union node *n, int flags)
8227 {
8228         struct job *jp;
8229         int backgnd = (n->type == NBACKGND);
8230         int status;
8231
8232         expredir(n->nredir.redirect);
8233         if (!backgnd && flags & EV_EXIT && !trap[0])
8234                 goto nofork;
8235         INT_OFF;
8236         jp = makejob(/*n,*/ 1);
8237         if (forkshell(jp, n, backgnd) == 0) {
8238                 INT_ON;
8239                 flags |= EV_EXIT;
8240                 if (backgnd)
8241                         flags &=~ EV_TESTED;
8242  nofork:
8243                 redirect(n->nredir.redirect, 0);
8244                 evaltreenr(n->nredir.n, flags);
8245                 /* never returns */
8246         }
8247         status = 0;
8248         if (!backgnd)
8249                 status = waitforjob(jp);
8250         exitstatus = status;
8251         INT_ON;
8252 }
8253
8254 /*
8255  * Compute the names of the files in a redirection list.
8256  */
8257 static void fixredir(union node *, const char *, int);
8258 static void
8259 expredir(union node *n)
8260 {
8261         union node *redir;
8262
8263         for (redir = n; redir; redir = redir->nfile.next) {
8264                 struct arglist fn;
8265
8266                 fn.list = NULL;
8267                 fn.lastp = &fn.list;
8268                 switch (redir->type) {
8269                 case NFROMTO:
8270                 case NFROM:
8271                 case NTO:
8272 #if ENABLE_ASH_BASH_COMPAT
8273                 case NTO2:
8274 #endif
8275                 case NCLOBBER:
8276                 case NAPPEND:
8277                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8278 #if ENABLE_ASH_BASH_COMPAT
8279  store_expfname:
8280 #endif
8281                         redir->nfile.expfname = fn.list->text;
8282                         break;
8283                 case NFROMFD:
8284                 case NTOFD: /* >& */
8285                         if (redir->ndup.vname) {
8286                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8287                                 if (fn.list == NULL)
8288                                         ash_msg_and_raise_error("redir error");
8289 #if ENABLE_ASH_BASH_COMPAT
8290 //FIXME: we used expandarg with different args!
8291                                 if (!isdigit_str9(fn.list->text)) {
8292                                         /* >&file, not >&fd */
8293                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
8294                                                 ash_msg_and_raise_error("redir error");
8295                                         redir->type = NTO2;
8296                                         goto store_expfname;
8297                                 }
8298 #endif
8299                                 fixredir(redir, fn.list->text, 1);
8300                         }
8301                         break;
8302                 }
8303         }
8304 }
8305
8306 /*
8307  * Evaluate a pipeline.  All the processes in the pipeline are children
8308  * of the process creating the pipeline.  (This differs from some versions
8309  * of the shell, which make the last process in a pipeline the parent
8310  * of all the rest.)
8311  */
8312 static void
8313 evalpipe(union node *n, int flags)
8314 {
8315         struct job *jp;
8316         struct nodelist *lp;
8317         int pipelen;
8318         int prevfd;
8319         int pip[2];
8320
8321         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8322         pipelen = 0;
8323         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8324                 pipelen++;
8325         flags |= EV_EXIT;
8326         INT_OFF;
8327         jp = makejob(/*n,*/ pipelen);
8328         prevfd = -1;
8329         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8330                 prehash(lp->n);
8331                 pip[1] = -1;
8332                 if (lp->next) {
8333                         if (pipe(pip) < 0) {
8334                                 close(prevfd);
8335                                 ash_msg_and_raise_error("pipe call failed");
8336                         }
8337                 }
8338                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8339                         INT_ON;
8340                         if (pip[1] >= 0) {
8341                                 close(pip[0]);
8342                         }
8343                         if (prevfd > 0) {
8344                                 dup2(prevfd, 0);
8345                                 close(prevfd);
8346                         }
8347                         if (pip[1] > 1) {
8348                                 dup2(pip[1], 1);
8349                                 close(pip[1]);
8350                         }
8351                         evaltreenr(lp->n, flags);
8352                         /* never returns */
8353                 }
8354                 if (prevfd >= 0)
8355                         close(prevfd);
8356                 prevfd = pip[0];
8357                 close(pip[1]);
8358         }
8359         if (n->npipe.pipe_backgnd == 0) {
8360                 exitstatus = waitforjob(jp);
8361                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
8362         }
8363         INT_ON;
8364 }
8365
8366 /*
8367  * Controls whether the shell is interactive or not.
8368  */
8369 static void
8370 setinteractive(int on)
8371 {
8372         static smallint is_interactive;
8373
8374         if (++on == is_interactive)
8375                 return;
8376         is_interactive = on;
8377         setsignal(SIGINT);
8378         setsignal(SIGQUIT);
8379         setsignal(SIGTERM);
8380 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8381         if (is_interactive > 1) {
8382                 /* Looks like they want an interactive shell */
8383                 static smallint did_banner;
8384
8385                 if (!did_banner) {
8386                         out1fmt(
8387                                 "\n\n"
8388                                 "%s built-in shell (ash)\n"
8389                                 "Enter 'help' for a list of built-in commands."
8390                                 "\n\n",
8391                                 bb_banner);
8392                         did_banner = 1;
8393                 }
8394         }
8395 #endif
8396 }
8397
8398 static void
8399 optschanged(void)
8400 {
8401 #if DEBUG
8402         opentrace();
8403 #endif
8404         setinteractive(iflag);
8405         setjobctl(mflag);
8406 #if ENABLE_FEATURE_EDITING_VI
8407         if (viflag)
8408                 line_input_state->flags |= VI_MODE;
8409         else
8410                 line_input_state->flags &= ~VI_MODE;
8411 #else
8412         viflag = 0; /* forcibly keep the option off */
8413 #endif
8414 }
8415
8416 static struct localvar *localvars;
8417
8418 /*
8419  * Called after a function returns.
8420  * Interrupts must be off.
8421  */
8422 static void
8423 poplocalvars(void)
8424 {
8425         struct localvar *lvp;
8426         struct var *vp;
8427
8428         while ((lvp = localvars) != NULL) {
8429                 localvars = lvp->next;
8430                 vp = lvp->vp;
8431                 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8432                 if (vp == NULL) {       /* $- saved */
8433                         memcpy(optlist, lvp->text, sizeof(optlist));
8434                         free((char*)lvp->text);
8435                         optschanged();
8436                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8437                         unsetvar(vp->text);
8438                 } else {
8439                         if (vp->func)
8440                                 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8441                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8442                                 free((char*)vp->text);
8443                         vp->flags = lvp->flags;
8444                         vp->text = lvp->text;
8445                 }
8446                 free(lvp);
8447         }
8448 }
8449
8450 static int
8451 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8452 {
8453         volatile struct shparam saveparam;
8454         struct localvar *volatile savelocalvars;
8455         struct jmploc *volatile savehandler;
8456         struct jmploc jmploc;
8457         int e;
8458
8459         saveparam = shellparam;
8460         savelocalvars = localvars;
8461         e = setjmp(jmploc.loc);
8462         if (e) {
8463                 goto funcdone;
8464         }
8465         INT_OFF;
8466         savehandler = exception_handler;
8467         exception_handler = &jmploc;
8468         localvars = NULL;
8469         shellparam.malloced = 0;
8470         func->count++;
8471         funcnest++;
8472         INT_ON;
8473         shellparam.nparam = argc - 1;
8474         shellparam.p = argv + 1;
8475 #if ENABLE_ASH_GETOPTS
8476         shellparam.optind = 1;
8477         shellparam.optoff = -1;
8478 #endif
8479         evaltree(&func->n, flags & EV_TESTED);
8480  funcdone:
8481         INT_OFF;
8482         funcnest--;
8483         freefunc(func);
8484         poplocalvars();
8485         localvars = savelocalvars;
8486         freeparam(&shellparam);
8487         shellparam = saveparam;
8488         exception_handler = savehandler;
8489         INT_ON;
8490         evalskip &= ~SKIPFUNC;
8491         return e;
8492 }
8493
8494 #if ENABLE_ASH_CMDCMD
8495 static char **
8496 parse_command_args(char **argv, const char **path)
8497 {
8498         char *cp, c;
8499
8500         for (;;) {
8501                 cp = *++argv;
8502                 if (!cp)
8503                         return 0;
8504                 if (*cp++ != '-')
8505                         break;
8506                 c = *cp++;
8507                 if (!c)
8508                         break;
8509                 if (c == '-' && !*cp) {
8510                         argv++;
8511                         break;
8512                 }
8513                 do {
8514                         switch (c) {
8515                         case 'p':
8516                                 *path = bb_default_path;
8517                                 break;
8518                         default:
8519                                 /* run 'typecmd' for other options */
8520                                 return 0;
8521                         }
8522                         c = *cp++;
8523                 } while (c);
8524         }
8525         return argv;
8526 }
8527 #endif
8528
8529 /*
8530  * Make a variable a local variable.  When a variable is made local, it's
8531  * value and flags are saved in a localvar structure.  The saved values
8532  * will be restored when the shell function returns.  We handle the name
8533  * "-" as a special case.
8534  */
8535 static void
8536 mklocal(char *name)
8537 {
8538         struct localvar *lvp;
8539         struct var **vpp;
8540         struct var *vp;
8541
8542         INT_OFF;
8543         lvp = ckzalloc(sizeof(struct localvar));
8544         if (LONE_DASH(name)) {
8545                 char *p;
8546                 p = ckmalloc(sizeof(optlist));
8547                 lvp->text = memcpy(p, optlist, sizeof(optlist));
8548                 vp = NULL;
8549         } else {
8550                 char *eq;
8551
8552                 vpp = hashvar(name);
8553                 vp = *findvar(vpp, name);
8554                 eq = strchr(name, '=');
8555                 if (vp == NULL) {
8556                         if (eq)
8557                                 setvareq(name, VSTRFIXED);
8558                         else
8559                                 setvar(name, NULL, VSTRFIXED);
8560                         vp = *vpp;      /* the new variable */
8561                         lvp->flags = VUNSET;
8562                 } else {
8563                         lvp->text = vp->text;
8564                         lvp->flags = vp->flags;
8565                         vp->flags |= VSTRFIXED|VTEXTFIXED;
8566                         if (eq)
8567                                 setvareq(name, 0);
8568                 }
8569         }
8570         lvp->vp = vp;
8571         lvp->next = localvars;
8572         localvars = lvp;
8573         INT_ON;
8574 }
8575
8576 /*
8577  * The "local" command.
8578  */
8579 static int
8580 localcmd(int argc UNUSED_PARAM, char **argv)
8581 {
8582         char *name;
8583
8584         argv = argptr;
8585         while ((name = *argv++) != NULL) {
8586                 mklocal(name);
8587         }
8588         return 0;
8589 }
8590
8591 static int
8592 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8593 {
8594         return 1;
8595 }
8596
8597 static int
8598 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8599 {
8600         return 0;
8601 }
8602
8603 static int
8604 execcmd(int argc UNUSED_PARAM, char **argv)
8605 {
8606         if (argv[1]) {
8607                 iflag = 0;              /* exit on error */
8608                 mflag = 0;
8609                 optschanged();
8610                 shellexec(argv + 1, pathval(), 0);
8611         }
8612         return 0;
8613 }
8614
8615 /*
8616  * The return command.
8617  */
8618 static int
8619 returncmd(int argc UNUSED_PARAM, char **argv)
8620 {
8621         /*
8622          * If called outside a function, do what ksh does;
8623          * skip the rest of the file.
8624          */
8625         evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8626         return argv[1] ? number(argv[1]) : exitstatus;
8627 }
8628
8629 /* Forward declarations for builtintab[] */
8630 static int breakcmd(int, char **);
8631 static int dotcmd(int, char **);
8632 static int evalcmd(int, char **);
8633 static int exitcmd(int, char **);
8634 static int exportcmd(int, char **);
8635 #if ENABLE_ASH_GETOPTS
8636 static int getoptscmd(int, char **);
8637 #endif
8638 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8639 static int helpcmd(int, char **);
8640 #endif
8641 #if ENABLE_ASH_MATH_SUPPORT
8642 static int letcmd(int, char **);
8643 #endif
8644 static int readcmd(int, char **);
8645 static int setcmd(int, char **);
8646 static int shiftcmd(int, char **);
8647 static int timescmd(int, char **);
8648 static int trapcmd(int, char **);
8649 static int umaskcmd(int, char **);
8650 static int unsetcmd(int, char **);
8651 static int ulimitcmd(int, char **);
8652
8653 #define BUILTIN_NOSPEC          "0"
8654 #define BUILTIN_SPECIAL         "1"
8655 #define BUILTIN_REGULAR         "2"
8656 #define BUILTIN_SPEC_REG        "3"
8657 #define BUILTIN_ASSIGN          "4"
8658 #define BUILTIN_SPEC_ASSG       "5"
8659 #define BUILTIN_REG_ASSG        "6"
8660 #define BUILTIN_SPEC_REG_ASSG   "7"
8661
8662 /* We do not handle [[ expr ]] bashism bash-compatibly,
8663  * we make it a synonym of [ expr ].
8664  * Basically, word splitting and pathname expansion should NOT be performed
8665  * Examples:
8666  * no word splitting:     a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8667  * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8668  * Additional operators:
8669  * || and && should work as -o and -a
8670  * =~ regexp match
8671  * Apart from the above, [[ expr ]] should work as [ expr ]
8672  */
8673
8674 #define echocmd   echo_main
8675 #define printfcmd printf_main
8676 #define testcmd   test_main
8677
8678 /* Keep these in proper order since it is searched via bsearch() */
8679 static const struct builtincmd builtintab[] = {
8680         { BUILTIN_SPEC_REG      ".", dotcmd },
8681         { BUILTIN_SPEC_REG      ":", truecmd },
8682 #if ENABLE_ASH_BUILTIN_TEST
8683         { BUILTIN_REGULAR       "[", testcmd },
8684 #if ENABLE_ASH_BASH_COMPAT
8685         { BUILTIN_REGULAR       "[[", testcmd },
8686 #endif
8687 #endif
8688 #if ENABLE_ASH_ALIAS
8689         { BUILTIN_REG_ASSG      "alias", aliascmd },
8690 #endif
8691 #if JOBS
8692         { BUILTIN_REGULAR       "bg", fg_bgcmd },
8693 #endif
8694         { BUILTIN_SPEC_REG      "break", breakcmd },
8695         { BUILTIN_REGULAR       "cd", cdcmd },
8696         { BUILTIN_NOSPEC        "chdir", cdcmd },
8697 #if ENABLE_ASH_CMDCMD
8698         { BUILTIN_REGULAR       "command", commandcmd },
8699 #endif
8700         { BUILTIN_SPEC_REG      "continue", breakcmd },
8701 #if ENABLE_ASH_BUILTIN_ECHO
8702         { BUILTIN_REGULAR       "echo", echocmd },
8703 #endif
8704         { BUILTIN_SPEC_REG      "eval", evalcmd },
8705         { BUILTIN_SPEC_REG      "exec", execcmd },
8706         { BUILTIN_SPEC_REG      "exit", exitcmd },
8707         { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8708         { BUILTIN_REGULAR       "false", falsecmd },
8709 #if JOBS
8710         { BUILTIN_REGULAR       "fg", fg_bgcmd },
8711 #endif
8712 #if ENABLE_ASH_GETOPTS
8713         { BUILTIN_REGULAR       "getopts", getoptscmd },
8714 #endif
8715         { BUILTIN_NOSPEC        "hash", hashcmd },
8716 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8717         { BUILTIN_NOSPEC        "help", helpcmd },
8718 #endif
8719 #if JOBS
8720         { BUILTIN_REGULAR       "jobs", jobscmd },
8721         { BUILTIN_REGULAR       "kill", killcmd },
8722 #endif
8723 #if ENABLE_ASH_MATH_SUPPORT
8724         { BUILTIN_NOSPEC        "let", letcmd },
8725 #endif
8726         { BUILTIN_ASSIGN        "local", localcmd },
8727 #if ENABLE_ASH_BUILTIN_PRINTF
8728         { BUILTIN_REGULAR       "printf", printfcmd },
8729 #endif
8730         { BUILTIN_NOSPEC        "pwd", pwdcmd },
8731         { BUILTIN_REGULAR       "read", readcmd },
8732         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8733         { BUILTIN_SPEC_REG      "return", returncmd },
8734         { BUILTIN_SPEC_REG      "set", setcmd },
8735         { BUILTIN_SPEC_REG      "shift", shiftcmd },
8736         { BUILTIN_SPEC_REG      "source", dotcmd },
8737 #if ENABLE_ASH_BUILTIN_TEST
8738         { BUILTIN_REGULAR       "test", testcmd },
8739 #endif
8740         { BUILTIN_SPEC_REG      "times", timescmd },
8741         { BUILTIN_SPEC_REG      "trap", trapcmd },
8742         { BUILTIN_REGULAR       "true", truecmd },
8743         { BUILTIN_NOSPEC        "type", typecmd },
8744         { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
8745         { BUILTIN_REGULAR       "umask", umaskcmd },
8746 #if ENABLE_ASH_ALIAS
8747         { BUILTIN_REGULAR       "unalias", unaliascmd },
8748 #endif
8749         { BUILTIN_SPEC_REG      "unset", unsetcmd },
8750         { BUILTIN_REGULAR       "wait", waitcmd },
8751 };
8752
8753 /* Should match the above table! */
8754 #define COMMANDCMD (builtintab + \
8755         2 + \
8756         1 * ENABLE_ASH_BUILTIN_TEST + \
8757         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8758         1 * ENABLE_ASH_ALIAS + \
8759         1 * ENABLE_ASH_JOB_CONTROL + \
8760         3)
8761 #define EXECCMD (builtintab + \
8762         2 + \
8763         1 * ENABLE_ASH_BUILTIN_TEST + \
8764         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8765         1 * ENABLE_ASH_ALIAS + \
8766         1 * ENABLE_ASH_JOB_CONTROL + \
8767         3 + \
8768         1 * ENABLE_ASH_CMDCMD + \
8769         1 + \
8770         ENABLE_ASH_BUILTIN_ECHO + \
8771         1)
8772
8773 /*
8774  * Search the table of builtin commands.
8775  */
8776 static struct builtincmd *
8777 find_builtin(const char *name)
8778 {
8779         struct builtincmd *bp;
8780
8781         bp = bsearch(
8782                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8783                 pstrcmp
8784         );
8785         return bp;
8786 }
8787
8788 /*
8789  * Execute a simple command.
8790  */
8791 static int
8792 isassignment(const char *p)
8793 {
8794         const char *q = endofname(p);
8795         if (p == q)
8796                 return 0;
8797         return *q == '=';
8798 }
8799 static int
8800 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8801 {
8802         /* Preserve exitstatus of a previous possible redirection
8803          * as POSIX mandates */
8804         return back_exitstatus;
8805 }
8806 static void
8807 evalcommand(union node *cmd, int flags)
8808 {
8809         static const struct builtincmd null_bltin = {
8810                 "\0\0", bltincmd /* why three NULs? */
8811         };
8812         struct stackmark smark;
8813         union node *argp;
8814         struct arglist arglist;
8815         struct arglist varlist;
8816         char **argv;
8817         int argc;
8818         const struct strlist *sp;
8819         struct cmdentry cmdentry;
8820         struct job *jp;
8821         char *lastarg;
8822         const char *path;
8823         int spclbltin;
8824         int status;
8825         char **nargv;
8826         struct builtincmd *bcmd;
8827         smallint cmd_is_exec;
8828         smallint pseudovarflag = 0;
8829
8830         /* First expand the arguments. */
8831         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8832         setstackmark(&smark);
8833         back_exitstatus = 0;
8834
8835         cmdentry.cmdtype = CMDBUILTIN;
8836         cmdentry.u.cmd = &null_bltin;
8837         varlist.lastp = &varlist.list;
8838         *varlist.lastp = NULL;
8839         arglist.lastp = &arglist.list;
8840         *arglist.lastp = NULL;
8841
8842         argc = 0;
8843         if (cmd->ncmd.args) {
8844                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8845                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8846         }
8847
8848         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8849                 struct strlist **spp;
8850
8851                 spp = arglist.lastp;
8852                 if (pseudovarflag && isassignment(argp->narg.text))
8853                         expandarg(argp, &arglist, EXP_VARTILDE);
8854                 else
8855                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8856
8857                 for (sp = *spp; sp; sp = sp->next)
8858                         argc++;
8859         }
8860
8861         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8862         for (sp = arglist.list; sp; sp = sp->next) {
8863                 TRACE(("evalcommand arg: %s\n", sp->text));
8864                 *nargv++ = sp->text;
8865         }
8866         *nargv = NULL;
8867
8868         lastarg = NULL;
8869         if (iflag && funcnest == 0 && argc > 0)
8870                 lastarg = nargv[-1];
8871
8872         preverrout_fd = 2;
8873         expredir(cmd->ncmd.redirect);
8874         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8875
8876         path = vpath.text;
8877         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8878                 struct strlist **spp;
8879                 char *p;
8880
8881                 spp = varlist.lastp;
8882                 expandarg(argp, &varlist, EXP_VARTILDE);
8883
8884                 /*
8885                  * Modify the command lookup path, if a PATH= assignment
8886                  * is present
8887                  */
8888                 p = (*spp)->text;
8889                 if (varequal(p, path))
8890                         path = p;
8891         }
8892
8893         /* Print the command if xflag is set. */
8894         if (xflag) {
8895                 int n;
8896                 const char *p = " %s";
8897
8898                 p++;
8899                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8900
8901                 sp = varlist.list;
8902                 for (n = 0; n < 2; n++) {
8903                         while (sp) {
8904                                 fdprintf(preverrout_fd, p, sp->text);
8905                                 sp = sp->next;
8906                                 if (*p == '%') {
8907                                         p--;
8908                                 }
8909                         }
8910                         sp = arglist.list;
8911                 }
8912                 safe_write(preverrout_fd, "\n", 1);
8913         }
8914
8915         cmd_is_exec = 0;
8916         spclbltin = -1;
8917
8918         /* Now locate the command. */
8919         if (argc) {
8920                 const char *oldpath;
8921                 int cmd_flag = DO_ERR;
8922
8923                 path += 5;
8924                 oldpath = path;
8925                 for (;;) {
8926                         find_command(argv[0], &cmdentry, cmd_flag, path);
8927                         if (cmdentry.cmdtype == CMDUNKNOWN) {
8928                                 flush_stderr();
8929                                 status = 127;
8930                                 goto bail;
8931                         }
8932
8933                         /* implement bltin and command here */
8934                         if (cmdentry.cmdtype != CMDBUILTIN)
8935                                 break;
8936                         if (spclbltin < 0)
8937                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8938                         if (cmdentry.u.cmd == EXECCMD)
8939                                 cmd_is_exec = 1;
8940 #if ENABLE_ASH_CMDCMD
8941                         if (cmdentry.u.cmd == COMMANDCMD) {
8942                                 path = oldpath;
8943                                 nargv = parse_command_args(argv, &path);
8944                                 if (!nargv)
8945                                         break;
8946                                 argc -= nargv - argv;
8947                                 argv = nargv;
8948                                 cmd_flag |= DO_NOFUNC;
8949                         } else
8950 #endif
8951                                 break;
8952                 }
8953         }
8954
8955         if (status) {
8956                 /* We have a redirection error. */
8957                 if (spclbltin > 0)
8958                         raise_exception(EXERROR);
8959  bail:
8960                 exitstatus = status;
8961                 goto out;
8962         }
8963
8964         /* Execute the command. */
8965         switch (cmdentry.cmdtype) {
8966         default:
8967
8968 #if ENABLE_FEATURE_SH_NOFORK
8969 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
8970  * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
8971         {
8972                 /* find_command() encodes applet_no as (-2 - applet_no) */
8973                 int applet_no = (- cmdentry.u.index - 2);
8974                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8975                         listsetvar(varlist.list, VEXPORT|VSTACK);
8976                         /* run <applet>_main() */
8977                         exitstatus = run_nofork_applet(applet_no, argv);
8978                         break;
8979                 }
8980         }
8981 #endif
8982                 /* Fork off a child process if necessary. */
8983                 if (!(flags & EV_EXIT) || trap[0]) {
8984                         INT_OFF;
8985                         jp = makejob(/*cmd,*/ 1);
8986                         if (forkshell(jp, cmd, FORK_FG) != 0) {
8987                                 exitstatus = waitforjob(jp);
8988                                 INT_ON;
8989                                 break;
8990                         }
8991                         FORCE_INT_ON;
8992                 }
8993                 listsetvar(varlist.list, VEXPORT|VSTACK);
8994                 shellexec(argv, path, cmdentry.u.index);
8995                 /* NOTREACHED */
8996
8997         case CMDBUILTIN:
8998                 cmdenviron = varlist.list;
8999                 if (cmdenviron) {
9000                         struct strlist *list = cmdenviron;
9001                         int i = VNOSET;
9002                         if (spclbltin > 0 || argc == 0) {
9003                                 i = 0;
9004                                 if (cmd_is_exec && argc > 1)
9005                                         i = VEXPORT;
9006                         }
9007                         listsetvar(list, i);
9008                 }
9009                 /* Tight loop with builtins only:
9010                  * "while kill -0 $child; do true; done"
9011                  * will never exit even if $child died, unless we do this
9012                  * to reap the zombie and make kill detect that it's gone: */
9013                 dowait(DOWAIT_NONBLOCK, NULL);
9014
9015                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9016                         int exit_status;
9017                         int i = exception_type;
9018                         if (i == EXEXIT)
9019                                 goto raise;
9020                         exit_status = 2;
9021                         if (i == EXINT)
9022                                 exit_status = 128 + SIGINT;
9023                         if (i == EXSIG)
9024                                 exit_status = 128 + pendingsig;
9025                         exitstatus = exit_status;
9026                         if (i == EXINT || spclbltin > 0) {
9027  raise:
9028                                 longjmp(exception_handler->loc, 1);
9029                         }
9030                         FORCE_INT_ON;
9031                 }
9032                 break;
9033
9034         case CMDFUNCTION:
9035                 listsetvar(varlist.list, 0);
9036                 /* See above for the rationale */
9037                 dowait(DOWAIT_NONBLOCK, NULL);
9038                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9039                         goto raise;
9040                 break;
9041         }
9042
9043  out:
9044         popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9045         if (lastarg) {
9046                 /* dsl: I think this is intended to be used to support
9047                  * '_' in 'vi' command mode during line editing...
9048                  * However I implemented that within libedit itself.
9049                  */
9050                 setvar("_", lastarg, 0);
9051         }
9052         popstackmark(&smark);
9053 }
9054
9055 static int
9056 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9057 {
9058         char *volatile savecmdname;
9059         struct jmploc *volatile savehandler;
9060         struct jmploc jmploc;
9061         int i;
9062
9063         savecmdname = commandname;
9064         i = setjmp(jmploc.loc);
9065         if (i)
9066                 goto cmddone;
9067         savehandler = exception_handler;
9068         exception_handler = &jmploc;
9069         commandname = argv[0];
9070         argptr = argv + 1;
9071         optptr = NULL;                  /* initialize nextopt */
9072         exitstatus = (*cmd->builtin)(argc, argv);
9073         flush_stdout_stderr();
9074  cmddone:
9075         exitstatus |= ferror(stdout);
9076         clearerr(stdout);
9077         commandname = savecmdname;
9078 //      exsig = 0;
9079         exception_handler = savehandler;
9080
9081         return i;
9082 }
9083
9084 static int
9085 goodname(const char *p)
9086 {
9087         return !*endofname(p);
9088 }
9089
9090
9091 /*
9092  * Search for a command.  This is called before we fork so that the
9093  * location of the command will be available in the parent as well as
9094  * the child.  The check for "goodname" is an overly conservative
9095  * check that the name will not be subject to expansion.
9096  */
9097 static void
9098 prehash(union node *n)
9099 {
9100         struct cmdentry entry;
9101
9102         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9103                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9104 }
9105
9106
9107 /* ============ Builtin commands
9108  *
9109  * Builtin commands whose functions are closely tied to evaluation
9110  * are implemented here.
9111  */
9112
9113 /*
9114  * Handle break and continue commands.  Break, continue, and return are
9115  * all handled by setting the evalskip flag.  The evaluation routines
9116  * above all check this flag, and if it is set they start skipping
9117  * commands rather than executing them.  The variable skipcount is
9118  * the number of loops to break/continue, or the number of function
9119  * levels to return.  (The latter is always 1.)  It should probably
9120  * be an error to break out of more loops than exist, but it isn't
9121  * in the standard shell so we don't make it one here.
9122  */
9123 static int
9124 breakcmd(int argc UNUSED_PARAM, char **argv)
9125 {
9126         int n = argv[1] ? number(argv[1]) : 1;
9127
9128         if (n <= 0)
9129                 ash_msg_and_raise_error(illnum, argv[1]);
9130         if (n > loopnest)
9131                 n = loopnest;
9132         if (n > 0) {
9133                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9134                 skipcount = n;
9135         }
9136         return 0;
9137 }
9138
9139
9140 /* ============ input.c
9141  *
9142  * This implements the input routines used by the parser.
9143  */
9144
9145 enum {
9146         INPUT_PUSH_FILE = 1,
9147         INPUT_NOFILE_OK = 2,
9148 };
9149
9150 static smallint checkkwd;
9151 /* values of checkkwd variable */
9152 #define CHKALIAS        0x1
9153 #define CHKKWD          0x2
9154 #define CHKNL           0x4
9155
9156 /*
9157  * Push a string back onto the input at this current parsefile level.
9158  * We handle aliases this way.
9159  */
9160 #if !ENABLE_ASH_ALIAS
9161 #define pushstring(s, ap) pushstring(s)
9162 #endif
9163 static void
9164 pushstring(char *s, struct alias *ap)
9165 {
9166         struct strpush *sp;
9167         int len;
9168
9169         len = strlen(s);
9170         INT_OFF;
9171         if (g_parsefile->strpush) {
9172                 sp = ckzalloc(sizeof(*sp));
9173                 sp->prev = g_parsefile->strpush;
9174         } else {
9175                 sp = &(g_parsefile->basestrpush);
9176         }
9177         g_parsefile->strpush = sp;
9178         sp->prev_string = g_parsefile->next_to_pgetc;
9179         sp->prev_left_in_line = g_parsefile->left_in_line;
9180 #if ENABLE_ASH_ALIAS
9181         sp->ap = ap;
9182         if (ap) {
9183                 ap->flag |= ALIASINUSE;
9184                 sp->string = s;
9185         }
9186 #endif
9187         g_parsefile->next_to_pgetc = s;
9188         g_parsefile->left_in_line = len;
9189         INT_ON;
9190 }
9191
9192 static void
9193 popstring(void)
9194 {
9195         struct strpush *sp = g_parsefile->strpush;
9196
9197         INT_OFF;
9198 #if ENABLE_ASH_ALIAS
9199         if (sp->ap) {
9200                 if (g_parsefile->next_to_pgetc[-1] == ' '
9201                  || g_parsefile->next_to_pgetc[-1] == '\t'
9202                 ) {
9203                         checkkwd |= CHKALIAS;
9204                 }
9205                 if (sp->string != sp->ap->val) {
9206                         free(sp->string);
9207                 }
9208                 sp->ap->flag &= ~ALIASINUSE;
9209                 if (sp->ap->flag & ALIASDEAD) {
9210                         unalias(sp->ap->name);
9211                 }
9212         }
9213 #endif
9214         g_parsefile->next_to_pgetc = sp->prev_string;
9215         g_parsefile->left_in_line = sp->prev_left_in_line;
9216         g_parsefile->strpush = sp->prev;
9217         if (sp != &(g_parsefile->basestrpush))
9218                 free(sp);
9219         INT_ON;
9220 }
9221
9222 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9223 //it peeks whether it is &>, and then pushes back both chars.
9224 //This function needs to save last *next_to_pgetc to buf[0]
9225 //to make two pungetc() reliable. Currently,
9226 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9227 static int
9228 preadfd(void)
9229 {
9230         int nr;
9231         char *buf = g_parsefile->buf;
9232
9233         g_parsefile->next_to_pgetc = buf;
9234 #if ENABLE_FEATURE_EDITING
9235  retry:
9236         if (!iflag || g_parsefile->fd != STDIN_FILENO)
9237                 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9238         else {
9239 #if ENABLE_FEATURE_TAB_COMPLETION
9240                 line_input_state->path_lookup = pathval();
9241 #endif
9242                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9243                 if (nr == 0) {
9244                         /* Ctrl+C pressed */
9245                         if (trap[SIGINT]) {
9246                                 buf[0] = '\n';
9247                                 buf[1] = '\0';
9248                                 raise(SIGINT);
9249                                 return 1;
9250                         }
9251                         goto retry;
9252                 }
9253                 if (nr < 0 && errno == 0) {
9254                         /* Ctrl+D pressed */
9255                         nr = 0;
9256                 }
9257         }
9258 #else
9259         nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9260 #endif
9261
9262 #if 0
9263 /* nonblock_safe_read() handles this problem */
9264         if (nr < 0) {
9265                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9266                         int flags = fcntl(0, F_GETFL);
9267                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9268                                 flags &= ~O_NONBLOCK;
9269                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9270                                         out2str("sh: turning off NDELAY mode\n");
9271                                         goto retry;
9272                                 }
9273                         }
9274                 }
9275         }
9276 #endif
9277         return nr;
9278 }
9279
9280 /*
9281  * Refill the input buffer and return the next input character:
9282  *
9283  * 1) If a string was pushed back on the input, pop it;
9284  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9285  *    or we are reading from a string so we can't refill the buffer,
9286  *    return EOF.
9287  * 3) If the is more stuff in this buffer, use it else call read to fill it.
9288  * 4) Process input up to the next newline, deleting nul characters.
9289  */
9290 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9291 #define pgetc_debug(...) ((void)0)
9292 /*
9293  * NB: due to SIT(c) internals (syntax_index_table[] vector),
9294  * pgetc() and related functions must return chars SIGN-EXTENDED into ints,
9295  * not zero-extended. Seems fragile to me. Affects only !USE_SIT_FUNCTION case,
9296  * so we can fix it by ditching !USE_SIT_FUNCTION if Unicode requires that.
9297  */
9298 static int
9299 preadbuffer(void)
9300 {
9301         char *q;
9302         int more;
9303
9304         while (g_parsefile->strpush) {
9305 #if ENABLE_ASH_ALIAS
9306                 if (g_parsefile->left_in_line == -1
9307                  && g_parsefile->strpush->ap
9308                  && g_parsefile->next_to_pgetc[-1] != ' '
9309                  && g_parsefile->next_to_pgetc[-1] != '\t'
9310                 ) {
9311                         pgetc_debug("preadbuffer PEOA");
9312                         return PEOA;
9313                 }
9314 #endif
9315                 popstring();
9316                 /* try "pgetc" now: */
9317                 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9318                                 g_parsefile->left_in_line,
9319                                 g_parsefile->next_to_pgetc,
9320                                 g_parsefile->next_to_pgetc);
9321                 if (--g_parsefile->left_in_line >= 0)
9322                         return (unsigned char)(*g_parsefile->next_to_pgetc++);
9323         }
9324         /* on both branches above g_parsefile->left_in_line < 0.
9325          * "pgetc" needs refilling.
9326          */
9327
9328         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9329          * pungetc() may increment it a few times.
9330          * Assuming it won't increment it to less than -90.
9331          */
9332         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9333                 pgetc_debug("preadbuffer PEOF1");
9334                 /* even in failure keep left_in_line and next_to_pgetc
9335                  * in lock step, for correct multi-layer pungetc.
9336                  * left_in_line was decremented before preadbuffer(),
9337                  * must inc next_to_pgetc: */
9338                 g_parsefile->next_to_pgetc++;
9339                 return PEOF;
9340         }
9341
9342         more = g_parsefile->left_in_buffer;
9343         if (more <= 0) {
9344                 flush_stdout_stderr();
9345  again:
9346                 more = preadfd();
9347                 if (more <= 0) {
9348                         /* don't try reading again */
9349                         g_parsefile->left_in_line = -99;
9350                         pgetc_debug("preadbuffer PEOF2");
9351                         g_parsefile->next_to_pgetc++;
9352                         return PEOF;
9353                 }
9354         }
9355
9356         /* Find out where's the end of line.
9357          * Set g_parsefile->left_in_line
9358          * and g_parsefile->left_in_buffer acordingly.
9359          * NUL chars are deleted.
9360          */
9361         q = g_parsefile->next_to_pgetc;
9362         for (;;) {
9363                 char c;
9364
9365                 more--;
9366
9367                 c = *q;
9368                 if (c == '\0') {
9369                         memmove(q, q + 1, more);
9370                 } else {
9371                         q++;
9372                         if (c == '\n') {
9373                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9374                                 break;
9375                         }
9376                 }
9377
9378                 if (more <= 0) {
9379                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9380                         if (g_parsefile->left_in_line < 0)
9381                                 goto again;
9382                         break;
9383                 }
9384         }
9385         g_parsefile->left_in_buffer = more;
9386
9387         if (vflag) {
9388                 char save = *q;
9389                 *q = '\0';
9390                 out2str(g_parsefile->next_to_pgetc);
9391                 *q = save;
9392         }
9393
9394         pgetc_debug("preadbuffer at %d:%p'%s'",
9395                         g_parsefile->left_in_line,
9396                         g_parsefile->next_to_pgetc,
9397                         g_parsefile->next_to_pgetc);
9398         return signed_char2int(*g_parsefile->next_to_pgetc++);
9399 }
9400
9401 #define pgetc_as_macro() \
9402         (--g_parsefile->left_in_line >= 0 \
9403         ? signed_char2int(*g_parsefile->next_to_pgetc++) \
9404         : preadbuffer() \
9405         )
9406
9407 static int
9408 pgetc(void)
9409 {
9410         pgetc_debug("pgetc_fast at %d:%p'%s'",
9411                         g_parsefile->left_in_line,
9412                         g_parsefile->next_to_pgetc,
9413                         g_parsefile->next_to_pgetc);
9414         return pgetc_as_macro();
9415 }
9416
9417 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9418 #define pgetc_fast() pgetc()
9419 #else
9420 #define pgetc_fast() pgetc_as_macro()
9421 #endif
9422
9423 /*
9424  * Same as pgetc(), but ignores PEOA.
9425  */
9426 #if ENABLE_ASH_ALIAS
9427 static int
9428 pgetc2(void)
9429 {
9430         int c;
9431         do {
9432                 pgetc_debug("pgetc_fast at %d:%p'%s'",
9433                                 g_parsefile->left_in_line,
9434                                 g_parsefile->next_to_pgetc,
9435                                 g_parsefile->next_to_pgetc);
9436                 c = pgetc_fast();
9437         } while (c == PEOA);
9438         return c;
9439 }
9440 #else
9441 #define pgetc2() pgetc()
9442 #endif
9443
9444 /*
9445  * Read a line from the script.
9446  */
9447 static char *
9448 pfgets(char *line, int len)
9449 {
9450         char *p = line;
9451         int nleft = len;
9452         int c;
9453
9454         while (--nleft > 0) {
9455                 c = pgetc2();
9456                 if (c == PEOF) {
9457                         if (p == line)
9458                                 return NULL;
9459                         break;
9460                 }
9461                 *p++ = c;
9462                 if (c == '\n')
9463                         break;
9464         }
9465         *p = '\0';
9466         return line;
9467 }
9468
9469 /*
9470  * Undo the last call to pgetc.  Only one character may be pushed back.
9471  * PEOF may be pushed back.
9472  */
9473 static void
9474 pungetc(void)
9475 {
9476         g_parsefile->left_in_line++;
9477         g_parsefile->next_to_pgetc--;
9478         pgetc_debug("pushed back to %d:%p'%s'",
9479                         g_parsefile->left_in_line,
9480                         g_parsefile->next_to_pgetc,
9481                         g_parsefile->next_to_pgetc);
9482 }
9483
9484 /*
9485  * To handle the "." command, a stack of input files is used.  Pushfile
9486  * adds a new entry to the stack and popfile restores the previous level.
9487  */
9488 static void
9489 pushfile(void)
9490 {
9491         struct parsefile *pf;
9492
9493         pf = ckzalloc(sizeof(*pf));
9494         pf->prev = g_parsefile;
9495         pf->fd = -1;
9496         /*pf->strpush = NULL; - ckzalloc did it */
9497         /*pf->basestrpush.prev = NULL;*/
9498         g_parsefile = pf;
9499 }
9500
9501 static void
9502 popfile(void)
9503 {
9504         struct parsefile *pf = g_parsefile;
9505
9506         INT_OFF;
9507         if (pf->fd >= 0)
9508                 close(pf->fd);
9509         free(pf->buf);
9510         while (pf->strpush)
9511                 popstring();
9512         g_parsefile = pf->prev;
9513         free(pf);
9514         INT_ON;
9515 }
9516
9517 /*
9518  * Return to top level.
9519  */
9520 static void
9521 popallfiles(void)
9522 {
9523         while (g_parsefile != &basepf)
9524                 popfile();
9525 }
9526
9527 /*
9528  * Close the file(s) that the shell is reading commands from.  Called
9529  * after a fork is done.
9530  */
9531 static void
9532 closescript(void)
9533 {
9534         popallfiles();
9535         if (g_parsefile->fd > 0) {
9536                 close(g_parsefile->fd);
9537                 g_parsefile->fd = 0;
9538         }
9539 }
9540
9541 /*
9542  * Like setinputfile, but takes an open file descriptor.  Call this with
9543  * interrupts off.
9544  */
9545 static void
9546 setinputfd(int fd, int push)
9547 {
9548         close_on_exec_on(fd);
9549         if (push) {
9550                 pushfile();
9551                 g_parsefile->buf = NULL;
9552         }
9553         g_parsefile->fd = fd;
9554         if (g_parsefile->buf == NULL)
9555                 g_parsefile->buf = ckmalloc(IBUFSIZ);
9556         g_parsefile->left_in_buffer = 0;
9557         g_parsefile->left_in_line = 0;
9558         g_parsefile->linno = 1;
9559 }
9560
9561 /*
9562  * Set the input to take input from a file.  If push is set, push the
9563  * old input onto the stack first.
9564  */
9565 static int
9566 setinputfile(const char *fname, int flags)
9567 {
9568         int fd;
9569         int fd2;
9570
9571         INT_OFF;
9572         fd = open(fname, O_RDONLY);
9573         if (fd < 0) {
9574                 if (flags & INPUT_NOFILE_OK)
9575                         goto out;
9576                 ash_msg_and_raise_error("can't open '%s'", fname);
9577         }
9578         if (fd < 10) {
9579                 fd2 = copyfd(fd, 10);
9580                 close(fd);
9581                 if (fd2 < 0)
9582                         ash_msg_and_raise_error("out of file descriptors");
9583                 fd = fd2;
9584         }
9585         setinputfd(fd, flags & INPUT_PUSH_FILE);
9586  out:
9587         INT_ON;
9588         return fd;
9589 }
9590
9591 /*
9592  * Like setinputfile, but takes input from a string.
9593  */
9594 static void
9595 setinputstring(char *string)
9596 {
9597         INT_OFF;
9598         pushfile();
9599         g_parsefile->next_to_pgetc = string;
9600         g_parsefile->left_in_line = strlen(string);
9601         g_parsefile->buf = NULL;
9602         g_parsefile->linno = 1;
9603         INT_ON;
9604 }
9605
9606
9607 /* ============ mail.c
9608  *
9609  * Routines to check for mail.
9610  */
9611
9612 #if ENABLE_ASH_MAIL
9613
9614 #define MAXMBOXES 10
9615
9616 /* times of mailboxes */
9617 static time_t mailtime[MAXMBOXES];
9618 /* Set if MAIL or MAILPATH is changed. */
9619 static smallint mail_var_path_changed;
9620
9621 /*
9622  * Print appropriate message(s) if mail has arrived.
9623  * If mail_var_path_changed is set,
9624  * then the value of MAIL has mail_var_path_changed,
9625  * so we just update the values.
9626  */
9627 static void
9628 chkmail(void)
9629 {
9630         const char *mpath;
9631         char *p;
9632         char *q;
9633         time_t *mtp;
9634         struct stackmark smark;
9635         struct stat statb;
9636
9637         setstackmark(&smark);
9638         mpath = mpathset() ? mpathval() : mailval();
9639         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9640                 p = padvance(&mpath, nullstr);
9641                 if (p == NULL)
9642                         break;
9643                 if (*p == '\0')
9644                         continue;
9645                 for (q = p; *q; q++)
9646                         continue;
9647 #if DEBUG
9648                 if (q[-1] != '/')
9649                         abort();
9650 #endif
9651                 q[-1] = '\0';                   /* delete trailing '/' */
9652                 if (stat(p, &statb) < 0) {
9653                         *mtp = 0;
9654                         continue;
9655                 }
9656                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9657                         fprintf(
9658                                 stderr, snlfmt,
9659                                 pathopt ? pathopt : "you have mail"
9660                         );
9661                 }
9662                 *mtp = statb.st_mtime;
9663         }
9664         mail_var_path_changed = 0;
9665         popstackmark(&smark);
9666 }
9667
9668 static void
9669 changemail(const char *val UNUSED_PARAM)
9670 {
9671         mail_var_path_changed = 1;
9672 }
9673
9674 #endif /* ASH_MAIL */
9675
9676
9677 /* ============ ??? */
9678
9679 /*
9680  * Set the shell parameters.
9681  */
9682 static void
9683 setparam(char **argv)
9684 {
9685         char **newparam;
9686         char **ap;
9687         int nparam;
9688
9689         for (nparam = 0; argv[nparam]; nparam++)
9690                 continue;
9691         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9692         while (*argv) {
9693                 *ap++ = ckstrdup(*argv++);
9694         }
9695         *ap = NULL;
9696         freeparam(&shellparam);
9697         shellparam.malloced = 1;
9698         shellparam.nparam = nparam;
9699         shellparam.p = newparam;
9700 #if ENABLE_ASH_GETOPTS
9701         shellparam.optind = 1;
9702         shellparam.optoff = -1;
9703 #endif
9704 }
9705
9706 /*
9707  * Process shell options.  The global variable argptr contains a pointer
9708  * to the argument list; we advance it past the options.
9709  *
9710  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9711  * For a non-interactive shell, an error condition encountered
9712  * by a special built-in ... shall cause the shell to write a diagnostic message
9713  * to standard error and exit as shown in the following table:
9714  * Error                                           Special Built-In
9715  * ...
9716  * Utility syntax error (option or operand error)  Shall exit
9717  * ...
9718  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9719  * we see that bash does not do that (set "finishes" with error code 1 instead,
9720  * and shell continues), and people rely on this behavior!
9721  * Testcase:
9722  * set -o barfoo 2>/dev/null
9723  * echo $?
9724  *
9725  * Oh well. Let's mimic that.
9726  */
9727 static int
9728 plus_minus_o(char *name, int val)
9729 {
9730         int i;
9731
9732         if (name) {
9733                 for (i = 0; i < NOPTS; i++) {
9734                         if (strcmp(name, optnames(i)) == 0) {
9735                                 optlist[i] = val;
9736                                 return 0;
9737                         }
9738                 }
9739                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9740                 return 1;
9741         }
9742         for (i = 0; i < NOPTS; i++) {
9743                 if (val) {
9744                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9745                 } else {
9746                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9747                 }
9748         }
9749         return 0;
9750 }
9751 static void
9752 setoption(int flag, int val)
9753 {
9754         int i;
9755
9756         for (i = 0; i < NOPTS; i++) {
9757                 if (optletters(i) == flag) {
9758                         optlist[i] = val;
9759                         return;
9760                 }
9761         }
9762         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9763         /* NOTREACHED */
9764 }
9765 static int
9766 options(int cmdline)
9767 {
9768         char *p;
9769         int val;
9770         int c;
9771
9772         if (cmdline)
9773                 minusc = NULL;
9774         while ((p = *argptr) != NULL) {
9775                 c = *p++;
9776                 if (c != '-' && c != '+')
9777                         break;
9778                 argptr++;
9779                 val = 0; /* val = 0 if c == '+' */
9780                 if (c == '-') {
9781                         val = 1;
9782                         if (p[0] == '\0' || LONE_DASH(p)) {
9783                                 if (!cmdline) {
9784                                         /* "-" means turn off -x and -v */
9785                                         if (p[0] == '\0')
9786                                                 xflag = vflag = 0;
9787                                         /* "--" means reset params */
9788                                         else if (*argptr == NULL)
9789                                                 setparam(argptr);
9790                                 }
9791                                 break;    /* "-" or  "--" terminates options */
9792                         }
9793                 }
9794                 /* first char was + or - */
9795                 while ((c = *p++) != '\0') {
9796                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9797                         if (c == 'c' && cmdline) {
9798                                 minusc = p;     /* command is after shell args */
9799                         } else if (c == 'o') {
9800                                 if (plus_minus_o(*argptr, val)) {
9801                                         /* it already printed err message */
9802                                         return 1; /* error */
9803                                 }
9804                                 if (*argptr)
9805                                         argptr++;
9806                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9807                                 isloginsh = 1;
9808                         /* bash does not accept +-login, we also won't */
9809                         } else if (cmdline && val && (c == '-')) { /* long options */
9810                                 if (strcmp(p, "login") == 0)
9811                                         isloginsh = 1;
9812                                 break;
9813                         } else {
9814                                 setoption(c, val);
9815                         }
9816                 }
9817         }
9818         return 0;
9819 }
9820
9821 /*
9822  * The shift builtin command.
9823  */
9824 static int
9825 shiftcmd(int argc UNUSED_PARAM, char **argv)
9826 {
9827         int n;
9828         char **ap1, **ap2;
9829
9830         n = 1;
9831         if (argv[1])
9832                 n = number(argv[1]);
9833         if (n > shellparam.nparam)
9834                 n = 0; /* bash compat, was = shellparam.nparam; */
9835         INT_OFF;
9836         shellparam.nparam -= n;
9837         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9838                 if (shellparam.malloced)
9839                         free(*ap1);
9840         }
9841         ap2 = shellparam.p;
9842         while ((*ap2++ = *ap1++) != NULL)
9843                 continue;
9844 #if ENABLE_ASH_GETOPTS
9845         shellparam.optind = 1;
9846         shellparam.optoff = -1;
9847 #endif
9848         INT_ON;
9849         return 0;
9850 }
9851
9852 /*
9853  * POSIX requires that 'set' (but not export or readonly) output the
9854  * variables in lexicographic order - by the locale's collating order (sigh).
9855  * Maybe we could keep them in an ordered balanced binary tree
9856  * instead of hashed lists.
9857  * For now just roll 'em through qsort for printing...
9858  */
9859 static int
9860 showvars(const char *sep_prefix, int on, int off)
9861 {
9862         const char *sep;
9863         char **ep, **epend;
9864
9865         ep = listvars(on, off, &epend);
9866         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9867
9868         sep = *sep_prefix ? " " : sep_prefix;
9869
9870         for (; ep < epend; ep++) {
9871                 const char *p;
9872                 const char *q;
9873
9874                 p = strchrnul(*ep, '=');
9875                 q = nullstr;
9876                 if (*p)
9877                         q = single_quote(++p);
9878                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9879         }
9880         return 0;
9881 }
9882
9883 /*
9884  * The set command builtin.
9885  */
9886 static int
9887 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9888 {
9889         int retval;
9890
9891         if (!argv[1])
9892                 return showvars(nullstr, 0, VUNSET);
9893         INT_OFF;
9894         retval = 1;
9895         if (!options(0)) { /* if no parse error... */
9896                 retval = 0;
9897                 optschanged();
9898                 if (*argptr != NULL) {
9899                         setparam(argptr);
9900                 }
9901         }
9902         INT_ON;
9903         return retval;
9904 }
9905
9906 #if ENABLE_ASH_RANDOM_SUPPORT
9907 static void
9908 change_random(const char *value)
9909 {
9910         /* Galois LFSR parameter */
9911         /* Taps at 32 31 29 1: */
9912         enum { MASK = 0x8000000b };
9913         /* Another example - taps at 32 31 30 10: */
9914         /* MASK = 0x00400007 */
9915
9916         if (value == NULL) {
9917                 /* "get", generate */
9918                 uint32_t t;
9919
9920                 /* LCG has period of 2^32 and alternating lowest bit */
9921                 random_LCG = 1664525 * random_LCG + 1013904223;
9922                 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9923                 t = (random_galois_LFSR << 1);
9924                 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9925                         t ^= MASK;
9926                 random_galois_LFSR = t;
9927                 /* Both are weak, combining them gives better randomness
9928                  * and ~2^64 period. & 0x7fff is probably bash compat
9929                  * for $RANDOM range. Combining with subtraction is
9930                  * just for fun. + and ^ would work equally well. */
9931                 t = (t - random_LCG) & 0x7fff;
9932                 /* set without recursion */
9933                 setvar(vrandom.text, utoa(t), VNOFUNC);
9934                 vrandom.flags &= ~VNOFUNC;
9935         } else {
9936                 /* set/reset */
9937                 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9938         }
9939 }
9940 #endif
9941
9942 #if ENABLE_ASH_GETOPTS
9943 static int
9944 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9945 {
9946         char *p, *q;
9947         char c = '?';
9948         int done = 0;
9949         int err = 0;
9950         char s[12];
9951         char **optnext;
9952
9953         if (*param_optind < 1)
9954                 return 1;
9955         optnext = optfirst + *param_optind - 1;
9956
9957         if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9958                 p = NULL;
9959         else
9960                 p = optnext[-1] + *optoff;
9961         if (p == NULL || *p == '\0') {
9962                 /* Current word is done, advance */
9963                 p = *optnext;
9964                 if (p == NULL || *p != '-' || *++p == '\0') {
9965  atend:
9966                         p = NULL;
9967                         done = 1;
9968                         goto out;
9969                 }
9970                 optnext++;
9971                 if (LONE_DASH(p))        /* check for "--" */
9972                         goto atend;
9973         }
9974
9975         c = *p++;
9976         for (q = optstr; *q != c;) {
9977                 if (*q == '\0') {
9978                         if (optstr[0] == ':') {
9979                                 s[0] = c;
9980                                 s[1] = '\0';
9981                                 err |= setvarsafe("OPTARG", s, 0);
9982                         } else {
9983                                 fprintf(stderr, "Illegal option -%c\n", c);
9984                                 unsetvar("OPTARG");
9985                         }
9986                         c = '?';
9987                         goto out;
9988                 }
9989                 if (*++q == ':')
9990                         q++;
9991         }
9992
9993         if (*++q == ':') {
9994                 if (*p == '\0' && (p = *optnext) == NULL) {
9995                         if (optstr[0] == ':') {
9996                                 s[0] = c;
9997                                 s[1] = '\0';
9998                                 err |= setvarsafe("OPTARG", s, 0);
9999                                 c = ':';
10000                         } else {
10001                                 fprintf(stderr, "No arg for -%c option\n", c);
10002                                 unsetvar("OPTARG");
10003                                 c = '?';
10004                         }
10005                         goto out;
10006                 }
10007
10008                 if (p == *optnext)
10009                         optnext++;
10010                 err |= setvarsafe("OPTARG", p, 0);
10011                 p = NULL;
10012         } else
10013                 err |= setvarsafe("OPTARG", nullstr, 0);
10014  out:
10015         *optoff = p ? p - *(optnext - 1) : -1;
10016         *param_optind = optnext - optfirst + 1;
10017         fmtstr(s, sizeof(s), "%d", *param_optind);
10018         err |= setvarsafe("OPTIND", s, VNOFUNC);
10019         s[0] = c;
10020         s[1] = '\0';
10021         err |= setvarsafe(optvar, s, 0);
10022         if (err) {
10023                 *param_optind = 1;
10024                 *optoff = -1;
10025                 flush_stdout_stderr();
10026                 raise_exception(EXERROR);
10027         }
10028         return done;
10029 }
10030
10031 /*
10032  * The getopts builtin.  Shellparam.optnext points to the next argument
10033  * to be processed.  Shellparam.optptr points to the next character to
10034  * be processed in the current argument.  If shellparam.optnext is NULL,
10035  * then it's the first time getopts has been called.
10036  */
10037 static int
10038 getoptscmd(int argc, char **argv)
10039 {
10040         char **optbase;
10041
10042         if (argc < 3)
10043                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10044         if (argc == 3) {
10045                 optbase = shellparam.p;
10046                 if (shellparam.optind > shellparam.nparam + 1) {
10047                         shellparam.optind = 1;
10048                         shellparam.optoff = -1;
10049                 }
10050         } else {
10051                 optbase = &argv[3];
10052                 if (shellparam.optind > argc - 2) {
10053                         shellparam.optind = 1;
10054                         shellparam.optoff = -1;
10055                 }
10056         }
10057
10058         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10059                         &shellparam.optoff);
10060 }
10061 #endif /* ASH_GETOPTS */
10062
10063
10064 /* ============ Shell parser */
10065
10066 struct heredoc {
10067         struct heredoc *next;   /* next here document in list */
10068         union node *here;       /* redirection node */
10069         char *eofmark;          /* string indicating end of input */
10070         smallint striptabs;     /* if set, strip leading tabs */
10071 };
10072
10073 static smallint tokpushback;           /* last token pushed back */
10074 static smallint parsebackquote;        /* nonzero if we are inside backquotes */
10075 static smallint quoteflag;             /* set if (part of) last token was quoted */
10076 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10077 static struct heredoc *heredoclist;    /* list of here documents to read */
10078 static char *wordtext;                 /* text of last word returned by readtoken */
10079 static struct nodelist *backquotelist;
10080 static union node *redirnode;
10081 static struct heredoc *heredoc;
10082 /*
10083  * NEOF is returned by parsecmd when it encounters an end of file.  It
10084  * must be distinct from NULL, so we use the address of a variable that
10085  * happens to be handy.
10086  */
10087 #define NEOF ((union node *)&tokpushback)
10088
10089 static void raise_error_syntax(const char *) NORETURN;
10090 static void
10091 raise_error_syntax(const char *msg)
10092 {
10093         ash_msg_and_raise_error("syntax error: %s", msg);
10094         /* NOTREACHED */
10095 }
10096
10097 /*
10098  * Called when an unexpected token is read during the parse.  The argument
10099  * is the token that is expected, or -1 if more than one type of token can
10100  * occur at this point.
10101  */
10102 static void raise_error_unexpected_syntax(int) NORETURN;
10103 static void
10104 raise_error_unexpected_syntax(int token)
10105 {
10106         char msg[64];
10107         int l;
10108
10109         l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10110         if (token >= 0)
10111                 sprintf(msg + l, " (expecting %s)", tokname(token));
10112         raise_error_syntax(msg);
10113         /* NOTREACHED */
10114 }
10115
10116 #define EOFMARKLEN 79
10117
10118 /* parsing is heavily cross-recursive, need these forward decls */
10119 static union node *andor(void);
10120 static union node *pipeline(void);
10121 static union node *parse_command(void);
10122 static void parseheredoc(void);
10123 static char peektoken(void);
10124 static int readtoken(void);
10125
10126 static union node *
10127 list(int nlflag)
10128 {
10129         union node *n1, *n2, *n3;
10130         int tok;
10131
10132         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10133         if (nlflag == 2 && peektoken())
10134                 return NULL;
10135         n1 = NULL;
10136         for (;;) {
10137                 n2 = andor();
10138                 tok = readtoken();
10139                 if (tok == TBACKGND) {
10140                         if (n2->type == NPIPE) {
10141                                 n2->npipe.pipe_backgnd = 1;
10142                         } else {
10143                                 if (n2->type != NREDIR) {
10144                                         n3 = stzalloc(sizeof(struct nredir));
10145                                         n3->nredir.n = n2;
10146                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10147                                         n2 = n3;
10148                                 }
10149                                 n2->type = NBACKGND;
10150                         }
10151                 }
10152                 if (n1 == NULL) {
10153                         n1 = n2;
10154                 } else {
10155                         n3 = stzalloc(sizeof(struct nbinary));
10156                         n3->type = NSEMI;
10157                         n3->nbinary.ch1 = n1;
10158                         n3->nbinary.ch2 = n2;
10159                         n1 = n3;
10160                 }
10161                 switch (tok) {
10162                 case TBACKGND:
10163                 case TSEMI:
10164                         tok = readtoken();
10165                         /* fall through */
10166                 case TNL:
10167                         if (tok == TNL) {
10168                                 parseheredoc();
10169                                 if (nlflag == 1)
10170                                         return n1;
10171                         } else {
10172                                 tokpushback = 1;
10173                         }
10174                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10175                         if (peektoken())
10176                                 return n1;
10177                         break;
10178                 case TEOF:
10179                         if (heredoclist)
10180                                 parseheredoc();
10181                         else
10182                                 pungetc();              /* push back EOF on input */
10183                         return n1;
10184                 default:
10185                         if (nlflag == 1)
10186                                 raise_error_unexpected_syntax(-1);
10187                         tokpushback = 1;
10188                         return n1;
10189                 }
10190         }
10191 }
10192
10193 static union node *
10194 andor(void)
10195 {
10196         union node *n1, *n2, *n3;
10197         int t;
10198
10199         n1 = pipeline();
10200         for (;;) {
10201                 t = readtoken();
10202                 if (t == TAND) {
10203                         t = NAND;
10204                 } else if (t == TOR) {
10205                         t = NOR;
10206                 } else {
10207                         tokpushback = 1;
10208                         return n1;
10209                 }
10210                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10211                 n2 = pipeline();
10212                 n3 = stzalloc(sizeof(struct nbinary));
10213                 n3->type = t;
10214                 n3->nbinary.ch1 = n1;
10215                 n3->nbinary.ch2 = n2;
10216                 n1 = n3;
10217         }
10218 }
10219
10220 static union node *
10221 pipeline(void)
10222 {
10223         union node *n1, *n2, *pipenode;
10224         struct nodelist *lp, *prev;
10225         int negate;
10226
10227         negate = 0;
10228         TRACE(("pipeline: entered\n"));
10229         if (readtoken() == TNOT) {
10230                 negate = !negate;
10231                 checkkwd = CHKKWD | CHKALIAS;
10232         } else
10233                 tokpushback = 1;
10234         n1 = parse_command();
10235         if (readtoken() == TPIPE) {
10236                 pipenode = stzalloc(sizeof(struct npipe));
10237                 pipenode->type = NPIPE;
10238                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10239                 lp = stzalloc(sizeof(struct nodelist));
10240                 pipenode->npipe.cmdlist = lp;
10241                 lp->n = n1;
10242                 do {
10243                         prev = lp;
10244                         lp = stzalloc(sizeof(struct nodelist));
10245                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10246                         lp->n = parse_command();
10247                         prev->next = lp;
10248                 } while (readtoken() == TPIPE);
10249                 lp->next = NULL;
10250                 n1 = pipenode;
10251         }
10252         tokpushback = 1;
10253         if (negate) {
10254                 n2 = stzalloc(sizeof(struct nnot));
10255                 n2->type = NNOT;
10256                 n2->nnot.com = n1;
10257                 return n2;
10258         }
10259         return n1;
10260 }
10261
10262 static union node *
10263 makename(void)
10264 {
10265         union node *n;
10266
10267         n = stzalloc(sizeof(struct narg));
10268         n->type = NARG;
10269         /*n->narg.next = NULL; - stzalloc did it */
10270         n->narg.text = wordtext;
10271         n->narg.backquote = backquotelist;
10272         return n;
10273 }
10274
10275 static void
10276 fixredir(union node *n, const char *text, int err)
10277 {
10278         int fd;
10279
10280         TRACE(("Fix redir %s %d\n", text, err));
10281         if (!err)
10282                 n->ndup.vname = NULL;
10283
10284         fd = bb_strtou(text, NULL, 10);
10285         if (!errno && fd >= 0)
10286                 n->ndup.dupfd = fd;
10287         else if (LONE_DASH(text))
10288                 n->ndup.dupfd = -1;
10289         else {
10290                 if (err)
10291                         raise_error_syntax("bad fd number");
10292                 n->ndup.vname = makename();
10293         }
10294 }
10295
10296 /*
10297  * Returns true if the text contains nothing to expand (no dollar signs
10298  * or backquotes).
10299  */
10300 static int
10301 noexpand(const char *text)
10302 {
10303         const char *p;
10304         char c;
10305
10306         p = text;
10307         while ((c = *p++) != '\0') {
10308                 if (c == CTLQUOTEMARK)
10309                         continue;
10310                 if (c == CTLESC)
10311                         p++;
10312                 else if (SIT((signed char)c, BASESYNTAX) == CCTL)
10313                         return 0;
10314         }
10315         return 1;
10316 }
10317
10318 static void
10319 parsefname(void)
10320 {
10321         union node *n = redirnode;
10322
10323         if (readtoken() != TWORD)
10324                 raise_error_unexpected_syntax(-1);
10325         if (n->type == NHERE) {
10326                 struct heredoc *here = heredoc;
10327                 struct heredoc *p;
10328                 int i;
10329
10330                 if (quoteflag == 0)
10331                         n->type = NXHERE;
10332                 TRACE(("Here document %d\n", n->type));
10333                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10334                         raise_error_syntax("illegal eof marker for << redirection");
10335                 rmescapes(wordtext);
10336                 here->eofmark = wordtext;
10337                 here->next = NULL;
10338                 if (heredoclist == NULL)
10339                         heredoclist = here;
10340                 else {
10341                         for (p = heredoclist; p->next; p = p->next)
10342                                 continue;
10343                         p->next = here;
10344                 }
10345         } else if (n->type == NTOFD || n->type == NFROMFD) {
10346                 fixredir(n, wordtext, 0);
10347         } else {
10348                 n->nfile.fname = makename();
10349         }
10350 }
10351
10352 static union node *
10353 simplecmd(void)
10354 {
10355         union node *args, **app;
10356         union node *n = NULL;
10357         union node *vars, **vpp;
10358         union node **rpp, *redir;
10359         int savecheckkwd;
10360 #if ENABLE_ASH_BASH_COMPAT
10361         smallint double_brackets_flag = 0;
10362 #endif
10363
10364         args = NULL;
10365         app = &args;
10366         vars = NULL;
10367         vpp = &vars;
10368         redir = NULL;
10369         rpp = &redir;
10370
10371         savecheckkwd = CHKALIAS;
10372         for (;;) {
10373                 int t;
10374                 checkkwd = savecheckkwd;
10375                 t = readtoken();
10376                 switch (t) {
10377 #if ENABLE_ASH_BASH_COMPAT
10378                 case TAND: /* "&&" */
10379                 case TOR: /* "||" */
10380                         if (!double_brackets_flag) {
10381                                 tokpushback = 1;
10382                                 goto out;
10383                         }
10384                         wordtext = (char *) (t == TAND ? "-a" : "-o");
10385 #endif
10386                 case TWORD:
10387                         n = stzalloc(sizeof(struct narg));
10388                         n->type = NARG;
10389                         /*n->narg.next = NULL; - stzalloc did it */
10390                         n->narg.text = wordtext;
10391 #if ENABLE_ASH_BASH_COMPAT
10392                         if (strcmp("[[", wordtext) == 0)
10393                                 double_brackets_flag = 1;
10394                         else if (strcmp("]]", wordtext) == 0)
10395                                 double_brackets_flag = 0;
10396 #endif
10397                         n->narg.backquote = backquotelist;
10398                         if (savecheckkwd && isassignment(wordtext)) {
10399                                 *vpp = n;
10400                                 vpp = &n->narg.next;
10401                         } else {
10402                                 *app = n;
10403                                 app = &n->narg.next;
10404                                 savecheckkwd = 0;
10405                         }
10406                         break;
10407                 case TREDIR:
10408                         *rpp = n = redirnode;
10409                         rpp = &n->nfile.next;
10410                         parsefname();   /* read name of redirection file */
10411                         break;
10412                 case TLP:
10413                         if (args && app == &args->narg.next
10414                          && !vars && !redir
10415                         ) {
10416                                 struct builtincmd *bcmd;
10417                                 const char *name;
10418
10419                                 /* We have a function */
10420                                 if (readtoken() != TRP)
10421                                         raise_error_unexpected_syntax(TRP);
10422                                 name = n->narg.text;
10423                                 if (!goodname(name)
10424                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10425                                 ) {
10426                                         raise_error_syntax("bad function name");
10427                                 }
10428                                 n->type = NDEFUN;
10429                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10430                                 n->narg.next = parse_command();
10431                                 return n;
10432                         }
10433                         /* fall through */
10434                 default:
10435                         tokpushback = 1;
10436                         goto out;
10437                 }
10438         }
10439  out:
10440         *app = NULL;
10441         *vpp = NULL;
10442         *rpp = NULL;
10443         n = stzalloc(sizeof(struct ncmd));
10444         n->type = NCMD;
10445         n->ncmd.args = args;
10446         n->ncmd.assign = vars;
10447         n->ncmd.redirect = redir;
10448         return n;
10449 }
10450
10451 static union node *
10452 parse_command(void)
10453 {
10454         union node *n1, *n2;
10455         union node *ap, **app;
10456         union node *cp, **cpp;
10457         union node *redir, **rpp;
10458         union node **rpp2;
10459         int t;
10460
10461         redir = NULL;
10462         rpp2 = &redir;
10463
10464         switch (readtoken()) {
10465         default:
10466                 raise_error_unexpected_syntax(-1);
10467                 /* NOTREACHED */
10468         case TIF:
10469                 n1 = stzalloc(sizeof(struct nif));
10470                 n1->type = NIF;
10471                 n1->nif.test = list(0);
10472                 if (readtoken() != TTHEN)
10473                         raise_error_unexpected_syntax(TTHEN);
10474                 n1->nif.ifpart = list(0);
10475                 n2 = n1;
10476                 while (readtoken() == TELIF) {
10477                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
10478                         n2 = n2->nif.elsepart;
10479                         n2->type = NIF;
10480                         n2->nif.test = list(0);
10481                         if (readtoken() != TTHEN)
10482                                 raise_error_unexpected_syntax(TTHEN);
10483                         n2->nif.ifpart = list(0);
10484                 }
10485                 if (lasttoken == TELSE)
10486                         n2->nif.elsepart = list(0);
10487                 else {
10488                         n2->nif.elsepart = NULL;
10489                         tokpushback = 1;
10490                 }
10491                 t = TFI;
10492                 break;
10493         case TWHILE:
10494         case TUNTIL: {
10495                 int got;
10496                 n1 = stzalloc(sizeof(struct nbinary));
10497                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10498                 n1->nbinary.ch1 = list(0);
10499                 got = readtoken();
10500                 if (got != TDO) {
10501                         TRACE(("expecting DO got %s %s\n", tokname(got),
10502                                         got == TWORD ? wordtext : ""));
10503                         raise_error_unexpected_syntax(TDO);
10504                 }
10505                 n1->nbinary.ch2 = list(0);
10506                 t = TDONE;
10507                 break;
10508         }
10509         case TFOR:
10510                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10511                         raise_error_syntax("bad for loop variable");
10512                 n1 = stzalloc(sizeof(struct nfor));
10513                 n1->type = NFOR;
10514                 n1->nfor.var = wordtext;
10515                 checkkwd = CHKKWD | CHKALIAS;
10516                 if (readtoken() == TIN) {
10517                         app = &ap;
10518                         while (readtoken() == TWORD) {
10519                                 n2 = stzalloc(sizeof(struct narg));
10520                                 n2->type = NARG;
10521                                 /*n2->narg.next = NULL; - stzalloc did it */
10522                                 n2->narg.text = wordtext;
10523                                 n2->narg.backquote = backquotelist;
10524                                 *app = n2;
10525                                 app = &n2->narg.next;
10526                         }
10527                         *app = NULL;
10528                         n1->nfor.args = ap;
10529                         if (lasttoken != TNL && lasttoken != TSEMI)
10530                                 raise_error_unexpected_syntax(-1);
10531                 } else {
10532                         n2 = stzalloc(sizeof(struct narg));
10533                         n2->type = NARG;
10534                         /*n2->narg.next = NULL; - stzalloc did it */
10535                         n2->narg.text = (char *)dolatstr;
10536                         /*n2->narg.backquote = NULL;*/
10537                         n1->nfor.args = n2;
10538                         /*
10539                          * Newline or semicolon here is optional (but note
10540                          * that the original Bourne shell only allowed NL).
10541                          */
10542                         if (lasttoken != TNL && lasttoken != TSEMI)
10543                                 tokpushback = 1;
10544                 }
10545                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10546                 if (readtoken() != TDO)
10547                         raise_error_unexpected_syntax(TDO);
10548                 n1->nfor.body = list(0);
10549                 t = TDONE;
10550                 break;
10551         case TCASE:
10552                 n1 = stzalloc(sizeof(struct ncase));
10553                 n1->type = NCASE;
10554                 if (readtoken() != TWORD)
10555                         raise_error_unexpected_syntax(TWORD);
10556                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10557                 n2->type = NARG;
10558                 /*n2->narg.next = NULL; - stzalloc did it */
10559                 n2->narg.text = wordtext;
10560                 n2->narg.backquote = backquotelist;
10561                 do {
10562                         checkkwd = CHKKWD | CHKALIAS;
10563                 } while (readtoken() == TNL);
10564                 if (lasttoken != TIN)
10565                         raise_error_unexpected_syntax(TIN);
10566                 cpp = &n1->ncase.cases;
10567  next_case:
10568                 checkkwd = CHKNL | CHKKWD;
10569                 t = readtoken();
10570                 while (t != TESAC) {
10571                         if (lasttoken == TLP)
10572                                 readtoken();
10573                         *cpp = cp = stzalloc(sizeof(struct nclist));
10574                         cp->type = NCLIST;
10575                         app = &cp->nclist.pattern;
10576                         for (;;) {
10577                                 *app = ap = stzalloc(sizeof(struct narg));
10578                                 ap->type = NARG;
10579                                 /*ap->narg.next = NULL; - stzalloc did it */
10580                                 ap->narg.text = wordtext;
10581                                 ap->narg.backquote = backquotelist;
10582                                 if (readtoken() != TPIPE)
10583                                         break;
10584                                 app = &ap->narg.next;
10585                                 readtoken();
10586                         }
10587                         //ap->narg.next = NULL;
10588                         if (lasttoken != TRP)
10589                                 raise_error_unexpected_syntax(TRP);
10590                         cp->nclist.body = list(2);
10591
10592                         cpp = &cp->nclist.next;
10593
10594                         checkkwd = CHKNL | CHKKWD;
10595                         t = readtoken();
10596                         if (t != TESAC) {
10597                                 if (t != TENDCASE)
10598                                         raise_error_unexpected_syntax(TENDCASE);
10599                                 goto next_case;
10600                         }
10601                 }
10602                 *cpp = NULL;
10603                 goto redir;
10604         case TLP:
10605                 n1 = stzalloc(sizeof(struct nredir));
10606                 n1->type = NSUBSHELL;
10607                 n1->nredir.n = list(0);
10608                 /*n1->nredir.redirect = NULL; - stzalloc did it */
10609                 t = TRP;
10610                 break;
10611         case TBEGIN:
10612                 n1 = list(0);
10613                 t = TEND;
10614                 break;
10615         case TWORD:
10616         case TREDIR:
10617                 tokpushback = 1;
10618                 return simplecmd();
10619         }
10620
10621         if (readtoken() != t)
10622                 raise_error_unexpected_syntax(t);
10623
10624  redir:
10625         /* Now check for redirection which may follow command */
10626         checkkwd = CHKKWD | CHKALIAS;
10627         rpp = rpp2;
10628         while (readtoken() == TREDIR) {
10629                 *rpp = n2 = redirnode;
10630                 rpp = &n2->nfile.next;
10631                 parsefname();
10632         }
10633         tokpushback = 1;
10634         *rpp = NULL;
10635         if (redir) {
10636                 if (n1->type != NSUBSHELL) {
10637                         n2 = stzalloc(sizeof(struct nredir));
10638                         n2->type = NREDIR;
10639                         n2->nredir.n = n1;
10640                         n1 = n2;
10641                 }
10642                 n1->nredir.redirect = redir;
10643         }
10644         return n1;
10645 }
10646
10647 #if ENABLE_ASH_BASH_COMPAT
10648 static int decode_dollar_squote(void)
10649 {
10650         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10651         int c, cnt;
10652         char *p;
10653         char buf[4];
10654
10655         c = pgetc();
10656         p = strchr(C_escapes, c);
10657         if (p) {
10658                 buf[0] = c;
10659                 p = buf;
10660                 cnt = 3;
10661                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10662                         do {
10663                                 c = pgetc();
10664                                 *++p = c;
10665                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
10666                         pungetc();
10667                 } else if (c == 'x') { /* \xHH */
10668                         do {
10669                                 c = pgetc();
10670                                 *++p = c;
10671                         } while (isxdigit(c) && --cnt);
10672                         pungetc();
10673                         if (cnt == 3) { /* \x but next char is "bad" */
10674                                 c = 'x';
10675                                 goto unrecognized;
10676                         }
10677                 } else { /* simple seq like \\ or \t */
10678                         p++;
10679                 }
10680                 *p = '\0';
10681                 p = buf;
10682                 c = bb_process_escape_sequence((void*)&p);
10683         } else { /* unrecognized "\z": print both chars unless ' or " */
10684                 if (c != '\'' && c != '"') {
10685  unrecognized:
10686                         c |= 0x100; /* "please encode \, then me" */
10687                 }
10688         }
10689         return c;
10690 }
10691 #endif
10692
10693 /*
10694  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10695  * is not NULL, read a here document.  In the latter case, eofmark is the
10696  * word which marks the end of the document and striptabs is true if
10697  * leading tabs should be stripped from the document.  The argument firstc
10698  * is the first character of the input token or document.
10699  *
10700  * Because C does not have internal subroutines, I have simulated them
10701  * using goto's to implement the subroutine linkage.  The following macros
10702  * will run code that appears at the end of readtoken1.
10703  */
10704 #define CHECKEND()      {goto checkend; checkend_return:;}
10705 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10706 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10707 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10708 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10709 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10710 static int
10711 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10712 {
10713         /* NB: syntax parameter fits into smallint */
10714         int c = firstc;
10715         char *out;
10716         int len;
10717         char line[EOFMARKLEN + 1];
10718         struct nodelist *bqlist;
10719         smallint quotef;
10720         smallint dblquote;
10721         smallint oldstyle;
10722         smallint prevsyntax; /* syntax before arithmetic */
10723 #if ENABLE_ASH_EXPAND_PRMT
10724         smallint pssyntax;   /* we are expanding a prompt string */
10725 #endif
10726         int varnest;         /* levels of variables expansion */
10727         int arinest;         /* levels of arithmetic expansion */
10728         int parenlevel;      /* levels of parens in arithmetic */
10729         int dqvarnest;       /* levels of variables expansion within double quotes */
10730
10731         USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10732
10733 #if __GNUC__
10734         /* Avoid longjmp clobbering */
10735         (void) &out;
10736         (void) &quotef;
10737         (void) &dblquote;
10738         (void) &varnest;
10739         (void) &arinest;
10740         (void) &parenlevel;
10741         (void) &dqvarnest;
10742         (void) &oldstyle;
10743         (void) &prevsyntax;
10744         (void) &syntax;
10745 #endif
10746         startlinno = g_parsefile->linno;
10747         bqlist = NULL;
10748         quotef = 0;
10749         oldstyle = 0;
10750         prevsyntax = 0;
10751 #if ENABLE_ASH_EXPAND_PRMT
10752         pssyntax = (syntax == PSSYNTAX);
10753         if (pssyntax)
10754                 syntax = DQSYNTAX;
10755 #endif
10756         dblquote = (syntax == DQSYNTAX);
10757         varnest = 0;
10758         arinest = 0;
10759         parenlevel = 0;
10760         dqvarnest = 0;
10761
10762         STARTSTACKSTR(out);
10763  loop:
10764         /* For each line, until end of word */
10765         {
10766                 CHECKEND();     /* set c to PEOF if at end of here document */
10767                 for (;;) {      /* until end of line or end of word */
10768                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10769                         switch (SIT(c, syntax)) {
10770                         case CNL:       /* '\n' */
10771                                 if (syntax == BASESYNTAX)
10772                                         goto endword;   /* exit outer loop */
10773                                 USTPUTC(c, out);
10774                                 g_parsefile->linno++;
10775                                 if (doprompt)
10776                                         setprompt(2);
10777                                 c = pgetc();
10778                                 goto loop;              /* continue outer loop */
10779                         case CWORD:
10780                                 USTPUTC(c, out);
10781                                 break;
10782                         case CCTL:
10783                                 if (eofmark == NULL || dblquote)
10784                                         USTPUTC(CTLESC, out);
10785 #if ENABLE_ASH_BASH_COMPAT
10786                                 if (c == '\\' && bash_dollar_squote) {
10787                                         c = decode_dollar_squote();
10788                                         if (c & 0x100) {
10789                                                 USTPUTC('\\', out);
10790                                                 c = (unsigned char)c;
10791                                         }
10792                                 }
10793 #endif
10794                                 USTPUTC(c, out);
10795                                 break;
10796                         case CBACK:     /* backslash */
10797                                 c = pgetc2();
10798                                 if (c == PEOF) {
10799                                         USTPUTC(CTLESC, out);
10800                                         USTPUTC('\\', out);
10801                                         pungetc();
10802                                 } else if (c == '\n') {
10803                                         if (doprompt)
10804                                                 setprompt(2);
10805                                 } else {
10806 #if ENABLE_ASH_EXPAND_PRMT
10807                                         if (c == '$' && pssyntax) {
10808                                                 USTPUTC(CTLESC, out);
10809                                                 USTPUTC('\\', out);
10810                                         }
10811 #endif
10812                                         if (dblquote && c != '\\'
10813                                          && c != '`' && c != '$'
10814                                          && (c != '"' || eofmark != NULL)
10815                                         ) {
10816                                                 USTPUTC(CTLESC, out);
10817                                                 USTPUTC('\\', out);
10818                                         }
10819                                         if (SIT(c, SQSYNTAX) == CCTL)
10820                                                 USTPUTC(CTLESC, out);
10821                                         USTPUTC(c, out);
10822                                         quotef = 1;
10823                                 }
10824                                 break;
10825                         case CSQUOTE:
10826                                 syntax = SQSYNTAX;
10827  quotemark:
10828                                 if (eofmark == NULL) {
10829                                         USTPUTC(CTLQUOTEMARK, out);
10830                                 }
10831                                 break;
10832                         case CDQUOTE:
10833                                 syntax = DQSYNTAX;
10834                                 dblquote = 1;
10835                                 goto quotemark;
10836                         case CENDQUOTE:
10837                                 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10838                                 if (eofmark != NULL && arinest == 0
10839                                  && varnest == 0
10840                                 ) {
10841                                         USTPUTC(c, out);
10842                                 } else {
10843                                         if (dqvarnest == 0) {
10844                                                 syntax = BASESYNTAX;
10845                                                 dblquote = 0;
10846                                         }
10847                                         quotef = 1;
10848                                         goto quotemark;
10849                                 }
10850                                 break;
10851                         case CVAR:      /* '$' */
10852                                 PARSESUB();             /* parse substitution */
10853                                 break;
10854                         case CENDVAR:   /* '}' */
10855                                 if (varnest > 0) {
10856                                         varnest--;
10857                                         if (dqvarnest > 0) {
10858                                                 dqvarnest--;
10859                                         }
10860                                         USTPUTC(CTLENDVAR, out);
10861                                 } else {
10862                                         USTPUTC(c, out);
10863                                 }
10864                                 break;
10865 #if ENABLE_ASH_MATH_SUPPORT
10866                         case CLP:       /* '(' in arithmetic */
10867                                 parenlevel++;
10868                                 USTPUTC(c, out);
10869                                 break;
10870                         case CRP:       /* ')' in arithmetic */
10871                                 if (parenlevel > 0) {
10872                                         USTPUTC(c, out);
10873                                         --parenlevel;
10874                                 } else {
10875                                         if (pgetc() == ')') {
10876                                                 if (--arinest == 0) {
10877                                                         USTPUTC(CTLENDARI, out);
10878                                                         syntax = prevsyntax;
10879                                                         dblquote = (syntax == DQSYNTAX);
10880                                                 } else
10881                                                         USTPUTC(')', out);
10882                                         } else {
10883                                                 /*
10884                                                  * unbalanced parens
10885                                                  *  (don't 2nd guess - no error)
10886                                                  */
10887                                                 pungetc();
10888                                                 USTPUTC(')', out);
10889                                         }
10890                                 }
10891                                 break;
10892 #endif
10893                         case CBQUOTE:   /* '`' */
10894                                 PARSEBACKQOLD();
10895                                 break;
10896                         case CENDFILE:
10897                                 goto endword;           /* exit outer loop */
10898                         case CIGN:
10899                                 break;
10900                         default:
10901                                 if (varnest == 0) {
10902 #if ENABLE_ASH_BASH_COMPAT
10903                                         if (c == '&') {
10904                                                 if (pgetc() == '>')
10905                                                         c = 0x100 + '>'; /* flag &> */
10906                                                 pungetc();
10907                                         }
10908 #endif
10909                                         goto endword;   /* exit outer loop */
10910                                 }
10911 #if ENABLE_ASH_ALIAS
10912                                 if (c != PEOA)
10913 #endif
10914                                         USTPUTC(c, out);
10915
10916                         }
10917                         c = pgetc_fast();
10918                 } /* for (;;) */
10919         }
10920  endword:
10921 #if ENABLE_ASH_MATH_SUPPORT
10922         if (syntax == ARISYNTAX)
10923                 raise_error_syntax("missing '))'");
10924 #endif
10925         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10926                 raise_error_syntax("unterminated quoted string");
10927         if (varnest != 0) {
10928                 startlinno = g_parsefile->linno;
10929                 /* { */
10930                 raise_error_syntax("missing '}'");
10931         }
10932         USTPUTC('\0', out);
10933         len = out - (char *)stackblock();
10934         out = stackblock();
10935         if (eofmark == NULL) {
10936                 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
10937                  && quotef == 0
10938                 ) {
10939                         if (isdigit_str9(out)) {
10940                                 PARSEREDIR(); /* passed as params: out, c */
10941                                 lasttoken = TREDIR;
10942                                 return lasttoken;
10943                         }
10944                         /* else: non-number X seen, interpret it
10945                          * as "NNNX>file" = "NNNX >file" */
10946                 }
10947                 pungetc();
10948         }
10949         quoteflag = quotef;
10950         backquotelist = bqlist;
10951         grabstackblock(len);
10952         wordtext = out;
10953         lasttoken = TWORD;
10954         return lasttoken;
10955 /* end of readtoken routine */
10956
10957 /*
10958  * Check to see whether we are at the end of the here document.  When this
10959  * is called, c is set to the first character of the next input line.  If
10960  * we are at the end of the here document, this routine sets the c to PEOF.
10961  */
10962 checkend: {
10963         if (eofmark) {
10964 #if ENABLE_ASH_ALIAS
10965                 if (c == PEOA) {
10966                         c = pgetc2();
10967                 }
10968 #endif
10969                 if (striptabs) {
10970                         while (c == '\t') {
10971                                 c = pgetc2();
10972                         }
10973                 }
10974                 if (c == *eofmark) {
10975                         if (pfgets(line, sizeof(line)) != NULL) {
10976                                 char *p, *q;
10977
10978                                 p = line;
10979                                 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10980                                         continue;
10981                                 if (*p == '\n' && *q == '\0') {
10982                                         c = PEOF;
10983                                         g_parsefile->linno++;
10984                                         needprompt = doprompt;
10985                                 } else {
10986                                         pushstring(line, NULL);
10987                                 }
10988                         }
10989                 }
10990         }
10991         goto checkend_return;
10992 }
10993
10994 /*
10995  * Parse a redirection operator.  The variable "out" points to a string
10996  * specifying the fd to be redirected.  The variable "c" contains the
10997  * first character of the redirection operator.
10998  */
10999 parseredir: {
11000         /* out is already checked to be a valid number or "" */
11001         int fd = (*out == '\0' ? -1 : atoi(out));
11002         union node *np;
11003
11004         np = stzalloc(sizeof(struct nfile));
11005         if (c == '>') {
11006                 np->nfile.fd = 1;
11007                 c = pgetc();
11008                 if (c == '>')
11009                         np->type = NAPPEND;
11010                 else if (c == '|')
11011                         np->type = NCLOBBER;
11012                 else if (c == '&')
11013                         np->type = NTOFD;
11014                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11015                 else {
11016                         np->type = NTO;
11017                         pungetc();
11018                 }
11019         }
11020 #if ENABLE_ASH_BASH_COMPAT
11021         else if (c == 0x100 + '>') { /* this flags &> redirection */
11022                 np->nfile.fd = 1;
11023                 pgetc(); /* this is '>', no need to check */
11024                 np->type = NTO2;
11025         }
11026 #endif
11027         else { /* c == '<' */
11028                 /*np->nfile.fd = 0; - stzalloc did it */
11029                 c = pgetc();
11030                 switch (c) {
11031                 case '<':
11032                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11033                                 np = stzalloc(sizeof(struct nhere));
11034                                 /*np->nfile.fd = 0; - stzalloc did it */
11035                         }
11036                         np->type = NHERE;
11037                         heredoc = stzalloc(sizeof(struct heredoc));
11038                         heredoc->here = np;
11039                         c = pgetc();
11040                         if (c == '-') {
11041                                 heredoc->striptabs = 1;
11042                         } else {
11043                                 /*heredoc->striptabs = 0; - stzalloc did it */
11044                                 pungetc();
11045                         }
11046                         break;
11047
11048                 case '&':
11049                         np->type = NFROMFD;
11050                         break;
11051
11052                 case '>':
11053                         np->type = NFROMTO;
11054                         break;
11055
11056                 default:
11057                         np->type = NFROM;
11058                         pungetc();
11059                         break;
11060                 }
11061         }
11062         if (fd >= 0)
11063                 np->nfile.fd = fd;
11064         redirnode = np;
11065         goto parseredir_return;
11066 }
11067
11068 /*
11069  * Parse a substitution.  At this point, we have read the dollar sign
11070  * and nothing else.
11071  */
11072
11073 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11074  * (assuming ascii char codes, as the original implementation did) */
11075 #define is_special(c) \
11076         (((unsigned)(c) - 33 < 32) \
11077                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11078 parsesub: {
11079         int subtype;
11080         int typeloc;
11081         int flags;
11082         char *p;
11083         static const char types[] ALIGN1 = "}-+?=";
11084
11085         c = pgetc();
11086         if (c <= PEOA_OR_PEOF
11087          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11088         ) {
11089 #if ENABLE_ASH_BASH_COMPAT
11090                 if (c == '\'')
11091                         bash_dollar_squote = 1;
11092                 else
11093 #endif
11094                         USTPUTC('$', out);
11095                 pungetc();
11096         } else if (c == '(') {  /* $(command) or $((arith)) */
11097                 if (pgetc() == '(') {
11098 #if ENABLE_ASH_MATH_SUPPORT
11099                         PARSEARITH();
11100 #else
11101                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11102 #endif
11103                 } else {
11104                         pungetc();
11105                         PARSEBACKQNEW();
11106                 }
11107         } else {
11108                 USTPUTC(CTLVAR, out);
11109                 typeloc = out - (char *)stackblock();
11110                 USTPUTC(VSNORMAL, out);
11111                 subtype = VSNORMAL;
11112                 if (c == '{') {
11113                         c = pgetc();
11114                         if (c == '#') {
11115                                 c = pgetc();
11116                                 if (c == '}')
11117                                         c = '#';
11118                                 else
11119                                         subtype = VSLENGTH;
11120                         } else
11121                                 subtype = 0;
11122                 }
11123                 if (c > PEOA_OR_PEOF && is_name(c)) {
11124                         do {
11125                                 STPUTC(c, out);
11126                                 c = pgetc();
11127                         } while (c > PEOA_OR_PEOF && is_in_name(c));
11128                 } else if (isdigit(c)) {
11129                         do {
11130                                 STPUTC(c, out);
11131                                 c = pgetc();
11132                         } while (isdigit(c));
11133                 } else if (is_special(c)) {
11134                         USTPUTC(c, out);
11135                         c = pgetc();
11136                 } else {
11137  badsub:
11138                         raise_error_syntax("bad substitution");
11139                 }
11140
11141                 STPUTC('=', out);
11142                 flags = 0;
11143                 if (subtype == 0) {
11144                         switch (c) {
11145                         case ':':
11146                                 c = pgetc();
11147 #if ENABLE_ASH_BASH_COMPAT
11148                                 if (c == ':' || c == '$' || isdigit(c)) {
11149                                         pungetc();
11150                                         subtype = VSSUBSTR;
11151                                         break;
11152                                 }
11153 #endif
11154                                 flags = VSNUL;
11155                                 /*FALLTHROUGH*/
11156                         default:
11157                                 p = strchr(types, c);
11158                                 if (p == NULL)
11159                                         goto badsub;
11160                                 subtype = p - types + VSNORMAL;
11161                                 break;
11162                         case '%':
11163                         case '#': {
11164                                 int cc = c;
11165                                 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11166                                 c = pgetc();
11167                                 if (c == cc)
11168                                         subtype++;
11169                                 else
11170                                         pungetc();
11171                                 break;
11172                         }
11173 #if ENABLE_ASH_BASH_COMPAT
11174                         case '/':
11175                                 subtype = VSREPLACE;
11176                                 c = pgetc();
11177                                 if (c == '/')
11178                                         subtype++; /* VSREPLACEALL */
11179                                 else
11180                                         pungetc();
11181                                 break;
11182 #endif
11183                         }
11184                 } else {
11185                         pungetc();
11186                 }
11187                 if (dblquote || arinest)
11188                         flags |= VSQUOTE;
11189                 *((char *)stackblock() + typeloc) = subtype | flags;
11190                 if (subtype != VSNORMAL) {
11191                         varnest++;
11192                         if (dblquote || arinest) {
11193                                 dqvarnest++;
11194                         }
11195                 }
11196         }
11197         goto parsesub_return;
11198 }
11199
11200 /*
11201  * Called to parse command substitutions.  Newstyle is set if the command
11202  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11203  * list of commands (passed by reference), and savelen is the number of
11204  * characters on the top of the stack which must be preserved.
11205  */
11206 parsebackq: {
11207         struct nodelist **nlpp;
11208         smallint savepbq;
11209         union node *n;
11210         char *volatile str;
11211         struct jmploc jmploc;
11212         struct jmploc *volatile savehandler;
11213         size_t savelen;
11214         smallint saveprompt = 0;
11215
11216 #ifdef __GNUC__
11217         (void) &saveprompt;
11218 #endif
11219         savepbq = parsebackquote;
11220         if (setjmp(jmploc.loc)) {
11221                 free(str);
11222                 parsebackquote = 0;
11223                 exception_handler = savehandler;
11224                 longjmp(exception_handler->loc, 1);
11225         }
11226         INT_OFF;
11227         str = NULL;
11228         savelen = out - (char *)stackblock();
11229         if (savelen > 0) {
11230                 str = ckmalloc(savelen);
11231                 memcpy(str, stackblock(), savelen);
11232         }
11233         savehandler = exception_handler;
11234         exception_handler = &jmploc;
11235         INT_ON;
11236         if (oldstyle) {
11237                 /* We must read until the closing backquote, giving special
11238                    treatment to some slashes, and then push the string and
11239                    reread it as input, interpreting it normally.  */
11240                 char *pout;
11241                 int pc;
11242                 size_t psavelen;
11243                 char *pstr;
11244
11245
11246                 STARTSTACKSTR(pout);
11247                 for (;;) {
11248                         if (needprompt) {
11249                                 setprompt(2);
11250                         }
11251                         pc = pgetc();
11252                         switch (pc) {
11253                         case '`':
11254                                 goto done;
11255
11256                         case '\\':
11257                                 pc = pgetc();
11258                                 if (pc == '\n') {
11259                                         g_parsefile->linno++;
11260                                         if (doprompt)
11261                                                 setprompt(2);
11262                                         /*
11263                                          * If eating a newline, avoid putting
11264                                          * the newline into the new character
11265                                          * stream (via the STPUTC after the
11266                                          * switch).
11267                                          */
11268                                         continue;
11269                                 }
11270                                 if (pc != '\\' && pc != '`' && pc != '$'
11271                                  && (!dblquote || pc != '"'))
11272                                         STPUTC('\\', pout);
11273                                 if (pc > PEOA_OR_PEOF) {
11274                                         break;
11275                                 }
11276                                 /* fall through */
11277
11278                         case PEOF:
11279 #if ENABLE_ASH_ALIAS
11280                         case PEOA:
11281 #endif
11282                                 startlinno = g_parsefile->linno;
11283                                 raise_error_syntax("EOF in backquote substitution");
11284
11285                         case '\n':
11286                                 g_parsefile->linno++;
11287                                 needprompt = doprompt;
11288                                 break;
11289
11290                         default:
11291                                 break;
11292                         }
11293                         STPUTC(pc, pout);
11294                 }
11295  done:
11296                 STPUTC('\0', pout);
11297                 psavelen = pout - (char *)stackblock();
11298                 if (psavelen > 0) {
11299                         pstr = grabstackstr(pout);
11300                         setinputstring(pstr);
11301                 }
11302         }
11303         nlpp = &bqlist;
11304         while (*nlpp)
11305                 nlpp = &(*nlpp)->next;
11306         *nlpp = stzalloc(sizeof(**nlpp));
11307         /* (*nlpp)->next = NULL; - stzalloc did it */
11308         parsebackquote = oldstyle;
11309
11310         if (oldstyle) {
11311                 saveprompt = doprompt;
11312                 doprompt = 0;
11313         }
11314
11315         n = list(2);
11316
11317         if (oldstyle)
11318                 doprompt = saveprompt;
11319         else if (readtoken() != TRP)
11320                 raise_error_unexpected_syntax(TRP);
11321
11322         (*nlpp)->n = n;
11323         if (oldstyle) {
11324                 /*
11325                  * Start reading from old file again, ignoring any pushed back
11326                  * tokens left from the backquote parsing
11327                  */
11328                 popfile();
11329                 tokpushback = 0;
11330         }
11331         while (stackblocksize() <= savelen)
11332                 growstackblock();
11333         STARTSTACKSTR(out);
11334         if (str) {
11335                 memcpy(out, str, savelen);
11336                 STADJUST(savelen, out);
11337                 INT_OFF;
11338                 free(str);
11339                 str = NULL;
11340                 INT_ON;
11341         }
11342         parsebackquote = savepbq;
11343         exception_handler = savehandler;
11344         if (arinest || dblquote)
11345                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11346         else
11347                 USTPUTC(CTLBACKQ, out);
11348         if (oldstyle)
11349                 goto parsebackq_oldreturn;
11350         goto parsebackq_newreturn;
11351 }
11352
11353 #if ENABLE_ASH_MATH_SUPPORT
11354 /*
11355  * Parse an arithmetic expansion (indicate start of one and set state)
11356  */
11357 parsearith: {
11358         if (++arinest == 1) {
11359                 prevsyntax = syntax;
11360                 syntax = ARISYNTAX;
11361                 USTPUTC(CTLARI, out);
11362                 if (dblquote)
11363                         USTPUTC('"', out);
11364                 else
11365                         USTPUTC(' ', out);
11366         } else {
11367                 /*
11368                  * we collapse embedded arithmetic expansion to
11369                  * parenthesis, which should be equivalent
11370                  */
11371                 USTPUTC('(', out);
11372         }
11373         goto parsearith_return;
11374 }
11375 #endif
11376
11377 } /* end of readtoken */
11378
11379 /*
11380  * Read the next input token.
11381  * If the token is a word, we set backquotelist to the list of cmds in
11382  *      backquotes.  We set quoteflag to true if any part of the word was
11383  *      quoted.
11384  * If the token is TREDIR, then we set redirnode to a structure containing
11385  *      the redirection.
11386  * In all cases, the variable startlinno is set to the number of the line
11387  *      on which the token starts.
11388  *
11389  * [Change comment:  here documents and internal procedures]
11390  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
11391  *  word parsing code into a separate routine.  In this case, readtoken
11392  *  doesn't need to have any internal procedures, but parseword does.
11393  *  We could also make parseoperator in essence the main routine, and
11394  *  have parseword (readtoken1?) handle both words and redirection.]
11395  */
11396 #define NEW_xxreadtoken
11397 #ifdef NEW_xxreadtoken
11398 /* singles must be first! */
11399 static const char xxreadtoken_chars[7] ALIGN1 = {
11400         '\n', '(', ')', /* singles */
11401         '&', '|', ';',  /* doubles */
11402         0
11403 };
11404
11405 #define xxreadtoken_singles 3
11406 #define xxreadtoken_doubles 3
11407
11408 static const char xxreadtoken_tokens[] ALIGN1 = {
11409         TNL, TLP, TRP,          /* only single occurrence allowed */
11410         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11411         TEOF,                   /* corresponds to trailing nul */
11412         TAND, TOR, TENDCASE     /* if double occurrence */
11413 };
11414
11415 static int
11416 xxreadtoken(void)
11417 {
11418         int c;
11419
11420         if (tokpushback) {
11421                 tokpushback = 0;
11422                 return lasttoken;
11423         }
11424         if (needprompt) {
11425                 setprompt(2);
11426         }
11427         startlinno = g_parsefile->linno;
11428         for (;;) {                      /* until token or start of word found */
11429                 c = pgetc_fast();
11430                 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11431                         continue;
11432
11433                 if (c == '#') {
11434                         while ((c = pgetc()) != '\n' && c != PEOF)
11435                                 continue;
11436                         pungetc();
11437                 } else if (c == '\\') {
11438                         if (pgetc() != '\n') {
11439                                 pungetc();
11440                                 break; /* return readtoken1(...) */
11441                         }
11442                         startlinno = ++g_parsefile->linno;
11443                         if (doprompt)
11444                                 setprompt(2);
11445                 } else {
11446                         const char *p;
11447
11448                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11449                         if (c != PEOF) {
11450                                 if (c == '\n') {
11451                                         g_parsefile->linno++;
11452                                         needprompt = doprompt;
11453                                 }
11454
11455                                 p = strchr(xxreadtoken_chars, c);
11456                                 if (p == NULL)
11457                                         break; /* return readtoken1(...) */
11458
11459                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11460                                         int cc = pgetc();
11461                                         if (cc == c) {    /* double occurrence? */
11462                                                 p += xxreadtoken_doubles + 1;
11463                                         } else {
11464                                                 pungetc();
11465 #if ENABLE_ASH_BASH_COMPAT
11466                                                 if (c == '&' && cc == '>') /* &> */
11467                                                         break; /* return readtoken1(...) */
11468 #endif
11469                                         }
11470                                 }
11471                         }
11472                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11473                         return lasttoken;
11474                 }
11475         } /* for (;;) */
11476
11477         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11478 }
11479 #else /* old xxreadtoken */
11480 #define RETURN(token)   return lasttoken = token
11481 static int
11482 xxreadtoken(void)
11483 {
11484         int c;
11485
11486         if (tokpushback) {
11487                 tokpushback = 0;
11488                 return lasttoken;
11489         }
11490         if (needprompt) {
11491                 setprompt(2);
11492         }
11493         startlinno = g_parsefile->linno;
11494         for (;;) {      /* until token or start of word found */
11495                 c = pgetc_fast();
11496                 switch (c) {
11497                 case ' ': case '\t':
11498 #if ENABLE_ASH_ALIAS
11499                 case PEOA:
11500 #endif
11501                         continue;
11502                 case '#':
11503                         while ((c = pgetc()) != '\n' && c != PEOF)
11504                                 continue;
11505                         pungetc();
11506                         continue;
11507                 case '\\':
11508                         if (pgetc() == '\n') {
11509                                 startlinno = ++g_parsefile->linno;
11510                                 if (doprompt)
11511                                         setprompt(2);
11512                                 continue;
11513                         }
11514                         pungetc();
11515                         goto breakloop;
11516                 case '\n':
11517                         g_parsefile->linno++;
11518                         needprompt = doprompt;
11519                         RETURN(TNL);
11520                 case PEOF:
11521                         RETURN(TEOF);
11522                 case '&':
11523                         if (pgetc() == '&')
11524                                 RETURN(TAND);
11525                         pungetc();
11526                         RETURN(TBACKGND);
11527                 case '|':
11528                         if (pgetc() == '|')
11529                                 RETURN(TOR);
11530                         pungetc();
11531                         RETURN(TPIPE);
11532                 case ';':
11533                         if (pgetc() == ';')
11534                                 RETURN(TENDCASE);
11535                         pungetc();
11536                         RETURN(TSEMI);
11537                 case '(':
11538                         RETURN(TLP);
11539                 case ')':
11540                         RETURN(TRP);
11541                 default:
11542                         goto breakloop;
11543                 }
11544         }
11545  breakloop:
11546         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11547 #undef RETURN
11548 }
11549 #endif /* old xxreadtoken */
11550
11551 static int
11552 readtoken(void)
11553 {
11554         int t;
11555 #if DEBUG
11556         smallint alreadyseen = tokpushback;
11557 #endif
11558
11559 #if ENABLE_ASH_ALIAS
11560  top:
11561 #endif
11562
11563         t = xxreadtoken();
11564
11565         /*
11566          * eat newlines
11567          */
11568         if (checkkwd & CHKNL) {
11569                 while (t == TNL) {
11570                         parseheredoc();
11571                         t = xxreadtoken();
11572                 }
11573         }
11574
11575         if (t != TWORD || quoteflag) {
11576                 goto out;
11577         }
11578
11579         /*
11580          * check for keywords
11581          */
11582         if (checkkwd & CHKKWD) {
11583                 const char *const *pp;
11584
11585                 pp = findkwd(wordtext);
11586                 if (pp) {
11587                         lasttoken = t = pp - tokname_array;
11588                         TRACE(("keyword %s recognized\n", tokname(t)));
11589                         goto out;
11590                 }
11591         }
11592
11593         if (checkkwd & CHKALIAS) {
11594 #if ENABLE_ASH_ALIAS
11595                 struct alias *ap;
11596                 ap = lookupalias(wordtext, 1);
11597                 if (ap != NULL) {
11598                         if (*ap->val) {
11599                                 pushstring(ap->val, ap);
11600                         }
11601                         goto top;
11602                 }
11603 #endif
11604         }
11605  out:
11606         checkkwd = 0;
11607 #if DEBUG
11608         if (!alreadyseen)
11609                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11610         else
11611                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11612 #endif
11613         return t;
11614 }
11615
11616 static char
11617 peektoken(void)
11618 {
11619         int t;
11620
11621         t = readtoken();
11622         tokpushback = 1;
11623         return tokname_array[t][0];
11624 }
11625
11626 /*
11627  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
11628  * valid parse tree indicating a blank line.)
11629  */
11630 static union node *
11631 parsecmd(int interact)
11632 {
11633         int t;
11634
11635         tokpushback = 0;
11636         doprompt = interact;
11637         if (doprompt)
11638                 setprompt(doprompt);
11639         needprompt = 0;
11640         t = readtoken();
11641         if (t == TEOF)
11642                 return NEOF;
11643         if (t == TNL)
11644                 return NULL;
11645         tokpushback = 1;
11646         return list(1);
11647 }
11648
11649 /*
11650  * Input any here documents.
11651  */
11652 static void
11653 parseheredoc(void)
11654 {
11655         struct heredoc *here;
11656         union node *n;
11657
11658         here = heredoclist;
11659         heredoclist = NULL;
11660
11661         while (here) {
11662                 if (needprompt) {
11663                         setprompt(2);
11664                 }
11665                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11666                                 here->eofmark, here->striptabs);
11667                 n = stzalloc(sizeof(struct narg));
11668                 n->narg.type = NARG;
11669                 /*n->narg.next = NULL; - stzalloc did it */
11670                 n->narg.text = wordtext;
11671                 n->narg.backquote = backquotelist;
11672                 here->here->nhere.doc = n;
11673                 here = here->next;
11674         }
11675 }
11676
11677
11678 /*
11679  * called by editline -- any expansions to the prompt should be added here.
11680  */
11681 #if ENABLE_ASH_EXPAND_PRMT
11682 static const char *
11683 expandstr(const char *ps)
11684 {
11685         union node n;
11686
11687         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
11688          * and token processing _can_ alter it (delete NULs etc). */
11689         setinputstring((char *)ps);
11690         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11691         popfile();
11692
11693         n.narg.type = NARG;
11694         n.narg.next = NULL;
11695         n.narg.text = wordtext;
11696         n.narg.backquote = backquotelist;
11697
11698         expandarg(&n, NULL, 0);
11699         return stackblock();
11700 }
11701 #endif
11702
11703 /*
11704  * Execute a command or commands contained in a string.
11705  */
11706 static int
11707 evalstring(char *s, int mask)
11708 {
11709         union node *n;
11710         struct stackmark smark;
11711         int skip;
11712
11713         setinputstring(s);
11714         setstackmark(&smark);
11715
11716         skip = 0;
11717         while ((n = parsecmd(0)) != NEOF) {
11718                 evaltree(n, 0);
11719                 popstackmark(&smark);
11720                 skip = evalskip;
11721                 if (skip)
11722                         break;
11723         }
11724         popfile();
11725
11726         skip &= mask;
11727         evalskip = skip;
11728         return skip;
11729 }
11730
11731 /*
11732  * The eval command.
11733  */
11734 static int
11735 evalcmd(int argc UNUSED_PARAM, char **argv)
11736 {
11737         char *p;
11738         char *concat;
11739
11740         if (argv[1]) {
11741                 p = argv[1];
11742                 argv += 2;
11743                 if (argv[0]) {
11744                         STARTSTACKSTR(concat);
11745                         for (;;) {
11746                                 concat = stack_putstr(p, concat);
11747                                 p = *argv++;
11748                                 if (p == NULL)
11749                                         break;
11750                                 STPUTC(' ', concat);
11751                         }
11752                         STPUTC('\0', concat);
11753                         p = grabstackstr(concat);
11754                 }
11755                 evalstring(p, ~SKIPEVAL);
11756
11757         }
11758         return exitstatus;
11759 }
11760
11761 /*
11762  * Read and execute commands.  "Top" is nonzero for the top level command
11763  * loop; it turns on prompting if the shell is interactive.
11764  */
11765 static int
11766 cmdloop(int top)
11767 {
11768         union node *n;
11769         struct stackmark smark;
11770         int inter;
11771         int numeof = 0;
11772
11773         TRACE(("cmdloop(%d) called\n", top));
11774         for (;;) {
11775                 int skip;
11776
11777                 setstackmark(&smark);
11778 #if JOBS
11779                 if (doing_jobctl)
11780                         showjobs(stderr, SHOW_CHANGED);
11781 #endif
11782                 inter = 0;
11783                 if (iflag && top) {
11784                         inter++;
11785 #if ENABLE_ASH_MAIL
11786                         chkmail();
11787 #endif
11788                 }
11789                 n = parsecmd(inter);
11790                 /* showtree(n); DEBUG */
11791                 if (n == NEOF) {
11792                         if (!top || numeof >= 50)
11793                                 break;
11794                         if (!stoppedjobs()) {
11795                                 if (!Iflag)
11796                                         break;
11797                                 out2str("\nUse \"exit\" to leave shell.\n");
11798                         }
11799                         numeof++;
11800                 } else if (nflag == 0) {
11801                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11802                         job_warning >>= 1;
11803                         numeof = 0;
11804                         evaltree(n, 0);
11805                 }
11806                 popstackmark(&smark);
11807                 skip = evalskip;
11808
11809                 if (skip) {
11810                         evalskip = 0;
11811                         return skip & SKIPEVAL;
11812                 }
11813         }
11814         return 0;
11815 }
11816
11817 /*
11818  * Take commands from a file.  To be compatible we should do a path
11819  * search for the file, which is necessary to find sub-commands.
11820  */
11821 static char *
11822 find_dot_file(char *name)
11823 {
11824         char *fullname;
11825         const char *path = pathval();
11826         struct stat statb;
11827
11828         /* don't try this for absolute or relative paths */
11829         if (strchr(name, '/'))
11830                 return name;
11831
11832         /* IIRC standards do not say whether . is to be searched.
11833          * And it is even smaller this way, making it unconditional for now:
11834          */
11835         if (1) { /* ENABLE_ASH_BASH_COMPAT */
11836                 fullname = name;
11837                 goto try_cur_dir;
11838         }
11839
11840         while ((fullname = padvance(&path, name)) != NULL) {
11841  try_cur_dir:
11842                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11843                         /*
11844                          * Don't bother freeing here, since it will
11845                          * be freed by the caller.
11846                          */
11847                         return fullname;
11848                 }
11849                 stunalloc(fullname);
11850         }
11851
11852         /* not found in the PATH */
11853         ash_msg_and_raise_error("%s: not found", name);
11854         /* NOTREACHED */
11855 }
11856
11857 static int
11858 dotcmd(int argc, char **argv)
11859 {
11860         struct strlist *sp;
11861         volatile struct shparam saveparam;
11862         int status = 0;
11863
11864         for (sp = cmdenviron; sp; sp = sp->next)
11865                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11866
11867         if (argv[1]) {        /* That's what SVR2 does */
11868                 char *fullname = find_dot_file(argv[1]);
11869                 argv += 2;
11870                 argc -= 2;
11871                 if (argc) { /* argc > 0, argv[0] != NULL */
11872                         saveparam = shellparam;
11873                         shellparam.malloced = 0;
11874                         shellparam.nparam = argc;
11875                         shellparam.p = argv;
11876                 };
11877
11878                 setinputfile(fullname, INPUT_PUSH_FILE);
11879                 commandname = fullname;
11880                 cmdloop(0);
11881                 popfile();
11882
11883                 if (argc) {
11884                         freeparam(&shellparam);
11885                         shellparam = saveparam;
11886                 };
11887                 status = exitstatus;
11888         }
11889         return status;
11890 }
11891
11892 static int
11893 exitcmd(int argc UNUSED_PARAM, char **argv)
11894 {
11895         if (stoppedjobs())
11896                 return 0;
11897         if (argv[1])
11898                 exitstatus = number(argv[1]);
11899         raise_exception(EXEXIT);
11900         /* NOTREACHED */
11901 }
11902
11903 /*
11904  * Read a file containing shell functions.
11905  */
11906 static void
11907 readcmdfile(char *name)
11908 {
11909         setinputfile(name, INPUT_PUSH_FILE);
11910         cmdloop(0);
11911         popfile();
11912 }
11913
11914
11915 /* ============ find_command inplementation */
11916
11917 /*
11918  * Resolve a command name.  If you change this routine, you may have to
11919  * change the shellexec routine as well.
11920  */
11921 static void
11922 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11923 {
11924         struct tblentry *cmdp;
11925         int idx;
11926         int prev;
11927         char *fullname;
11928         struct stat statb;
11929         int e;
11930         int updatetbl;
11931         struct builtincmd *bcmd;
11932
11933         /* If name contains a slash, don't use PATH or hash table */
11934         if (strchr(name, '/') != NULL) {
11935                 entry->u.index = -1;
11936                 if (act & DO_ABS) {
11937                         while (stat(name, &statb) < 0) {
11938 #ifdef SYSV
11939                                 if (errno == EINTR)
11940                                         continue;
11941 #endif
11942                                 entry->cmdtype = CMDUNKNOWN;
11943                                 return;
11944                         }
11945                 }
11946                 entry->cmdtype = CMDNORMAL;
11947                 return;
11948         }
11949
11950 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11951
11952         updatetbl = (path == pathval());
11953         if (!updatetbl) {
11954                 act |= DO_ALTPATH;
11955                 if (strstr(path, "%builtin") != NULL)
11956                         act |= DO_ALTBLTIN;
11957         }
11958
11959         /* If name is in the table, check answer will be ok */
11960         cmdp = cmdlookup(name, 0);
11961         if (cmdp != NULL) {
11962                 int bit;
11963
11964                 switch (cmdp->cmdtype) {
11965                 default:
11966 #if DEBUG
11967                         abort();
11968 #endif
11969                 case CMDNORMAL:
11970                         bit = DO_ALTPATH;
11971                         break;
11972                 case CMDFUNCTION:
11973                         bit = DO_NOFUNC;
11974                         break;
11975                 case CMDBUILTIN:
11976                         bit = DO_ALTBLTIN;
11977                         break;
11978                 }
11979                 if (act & bit) {
11980                         updatetbl = 0;
11981                         cmdp = NULL;
11982                 } else if (cmdp->rehash == 0)
11983                         /* if not invalidated by cd, we're done */
11984                         goto success;
11985         }
11986
11987         /* If %builtin not in path, check for builtin next */
11988         bcmd = find_builtin(name);
11989         if (bcmd) {
11990                 if (IS_BUILTIN_REGULAR(bcmd))
11991                         goto builtin_success;
11992                 if (act & DO_ALTPATH) {
11993                         if (!(act & DO_ALTBLTIN))
11994                                 goto builtin_success;
11995                 } else if (builtinloc <= 0) {
11996                         goto builtin_success;
11997                 }
11998         }
11999
12000 #if ENABLE_FEATURE_SH_STANDALONE
12001         {
12002                 int applet_no = find_applet_by_name(name);
12003                 if (applet_no >= 0) {
12004                         entry->cmdtype = CMDNORMAL;
12005                         entry->u.index = -2 - applet_no;
12006                         return;
12007                 }
12008         }
12009 #endif
12010
12011         /* We have to search path. */
12012         prev = -1;              /* where to start */
12013         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12014                 if (cmdp->cmdtype == CMDBUILTIN)
12015                         prev = builtinloc;
12016                 else
12017                         prev = cmdp->param.index;
12018         }
12019
12020         e = ENOENT;
12021         idx = -1;
12022  loop:
12023         while ((fullname = padvance(&path, name)) != NULL) {
12024                 stunalloc(fullname);
12025                 /* NB: code below will still use fullname
12026                  * despite it being "unallocated" */
12027                 idx++;
12028                 if (pathopt) {
12029                         if (prefix(pathopt, "builtin")) {
12030                                 if (bcmd)
12031                                         goto builtin_success;
12032                                 continue;
12033                         }
12034                         if ((act & DO_NOFUNC)
12035                          || !prefix(pathopt, "func")
12036                         ) {     /* ignore unimplemented options */
12037                                 continue;
12038                         }
12039                 }
12040                 /* if rehash, don't redo absolute path names */
12041                 if (fullname[0] == '/' && idx <= prev) {
12042                         if (idx < prev)
12043                                 continue;
12044                         TRACE(("searchexec \"%s\": no change\n", name));
12045                         goto success;
12046                 }
12047                 while (stat(fullname, &statb) < 0) {
12048 #ifdef SYSV
12049                         if (errno == EINTR)
12050                                 continue;
12051 #endif
12052                         if (errno != ENOENT && errno != ENOTDIR)
12053                                 e = errno;
12054                         goto loop;
12055                 }
12056                 e = EACCES;     /* if we fail, this will be the error */
12057                 if (!S_ISREG(statb.st_mode))
12058                         continue;
12059                 if (pathopt) {          /* this is a %func directory */
12060                         stalloc(strlen(fullname) + 1);
12061                         /* NB: stalloc will return space pointed by fullname
12062                          * (because we don't have any intervening allocations
12063                          * between stunalloc above and this stalloc) */
12064                         readcmdfile(fullname);
12065                         cmdp = cmdlookup(name, 0);
12066                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12067                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12068                         stunalloc(fullname);
12069                         goto success;
12070                 }
12071                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12072                 if (!updatetbl) {
12073                         entry->cmdtype = CMDNORMAL;
12074                         entry->u.index = idx;
12075                         return;
12076                 }
12077                 INT_OFF;
12078                 cmdp = cmdlookup(name, 1);
12079                 cmdp->cmdtype = CMDNORMAL;
12080                 cmdp->param.index = idx;
12081                 INT_ON;
12082                 goto success;
12083         }
12084
12085         /* We failed.  If there was an entry for this command, delete it */
12086         if (cmdp && updatetbl)
12087                 delete_cmd_entry();
12088         if (act & DO_ERR)
12089                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12090         entry->cmdtype = CMDUNKNOWN;
12091         return;
12092
12093  builtin_success:
12094         if (!updatetbl) {
12095                 entry->cmdtype = CMDBUILTIN;
12096                 entry->u.cmd = bcmd;
12097                 return;
12098         }
12099         INT_OFF;
12100         cmdp = cmdlookup(name, 1);
12101         cmdp->cmdtype = CMDBUILTIN;
12102         cmdp->param.cmd = bcmd;
12103         INT_ON;
12104  success:
12105         cmdp->rehash = 0;
12106         entry->cmdtype = cmdp->cmdtype;
12107         entry->u = cmdp->param;
12108 }
12109
12110
12111 /* ============ trap.c */
12112
12113 /*
12114  * The trap builtin.
12115  */
12116 static int
12117 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12118 {
12119         char *action;
12120         char **ap;
12121         int signo;
12122
12123         nextopt(nullstr);
12124         ap = argptr;
12125         if (!*ap) {
12126                 for (signo = 0; signo < NSIG; signo++) {
12127                         if (trap[signo] != NULL) {
12128                                 out1fmt("trap -- %s %s\n",
12129                                                 single_quote(trap[signo]),
12130                                                 get_signame(signo));
12131                         }
12132                 }
12133                 return 0;
12134         }
12135         action = NULL;
12136         if (ap[1])
12137                 action = *ap++;
12138         while (*ap) {
12139                 signo = get_signum(*ap);
12140                 if (signo < 0)
12141                         ash_msg_and_raise_error("%s: bad trap", *ap);
12142                 INT_OFF;
12143                 if (action) {
12144                         if (LONE_DASH(action))
12145                                 action = NULL;
12146                         else
12147                                 action = ckstrdup(action);
12148                 }
12149                 free(trap[signo]);
12150                 trap[signo] = action;
12151                 if (signo != 0)
12152                         setsignal(signo);
12153                 INT_ON;
12154                 ap++;
12155         }
12156         return 0;
12157 }
12158
12159
12160 /* ============ Builtins */
12161
12162 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12163 /*
12164  * Lists available builtins
12165  */
12166 static int
12167 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12168 {
12169         unsigned col;
12170         unsigned i;
12171
12172         out1fmt("\nBuilt-in commands:\n-------------------\n");
12173         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12174                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12175                                         builtintab[i].name + 1);
12176                 if (col > 60) {
12177                         out1fmt("\n");
12178                         col = 0;
12179                 }
12180         }
12181 #if ENABLE_FEATURE_SH_STANDALONE
12182         {
12183                 const char *a = applet_names;
12184                 while (*a) {
12185                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12186                         if (col > 60) {
12187                                 out1fmt("\n");
12188                                 col = 0;
12189                         }
12190                         a += strlen(a) + 1;
12191                 }
12192         }
12193 #endif
12194         out1fmt("\n\n");
12195         return EXIT_SUCCESS;
12196 }
12197 #endif /* FEATURE_SH_EXTRA_QUIET */
12198
12199 /*
12200  * The export and readonly commands.
12201  */
12202 static int
12203 exportcmd(int argc UNUSED_PARAM, char **argv)
12204 {
12205         struct var *vp;
12206         char *name;
12207         const char *p;
12208         char **aptr;
12209         int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12210
12211         if (nextopt("p") != 'p') {
12212                 aptr = argptr;
12213                 name = *aptr;
12214                 if (name) {
12215                         do {
12216                                 p = strchr(name, '=');
12217                                 if (p != NULL) {
12218                                         p++;
12219                                 } else {
12220                                         vp = *findvar(hashvar(name), name);
12221                                         if (vp) {
12222                                                 vp->flags |= flag;
12223                                                 continue;
12224                                         }
12225                                 }
12226                                 setvar(name, p, flag);
12227                         } while ((name = *++aptr) != NULL);
12228                         return 0;
12229                 }
12230         }
12231         showvars(argv[0], flag, 0);
12232         return 0;
12233 }
12234
12235 /*
12236  * Delete a function if it exists.
12237  */
12238 static void
12239 unsetfunc(const char *name)
12240 {
12241         struct tblentry *cmdp;
12242
12243         cmdp = cmdlookup(name, 0);
12244         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12245                 delete_cmd_entry();
12246 }
12247
12248 /*
12249  * The unset builtin command.  We unset the function before we unset the
12250  * variable to allow a function to be unset when there is a readonly variable
12251  * with the same name.
12252  */
12253 static int
12254 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12255 {
12256         char **ap;
12257         int i;
12258         int flag = 0;
12259         int ret = 0;
12260
12261         while ((i = nextopt("vf")) != '\0') {
12262                 flag = i;
12263         }
12264
12265         for (ap = argptr; *ap; ap++) {
12266                 if (flag != 'f') {
12267                         i = unsetvar(*ap);
12268                         ret |= i;
12269                         if (!(i & 2))
12270                                 continue;
12271                 }
12272                 if (flag != 'v')
12273                         unsetfunc(*ap);
12274         }
12275         return ret & 1;
12276 }
12277
12278
12279 /*      setmode.c      */
12280
12281 #include <sys/times.h>
12282
12283 static const unsigned char timescmd_str[] ALIGN1 = {
12284         ' ',  offsetof(struct tms, tms_utime),
12285         '\n', offsetof(struct tms, tms_stime),
12286         ' ',  offsetof(struct tms, tms_cutime),
12287         '\n', offsetof(struct tms, tms_cstime),
12288         0
12289 };
12290
12291 static int
12292 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12293 {
12294         long clk_tck, s, t;
12295         const unsigned char *p;
12296         struct tms buf;
12297
12298         clk_tck = sysconf(_SC_CLK_TCK);
12299         times(&buf);
12300
12301         p = timescmd_str;
12302         do {
12303                 t = *(clock_t *)(((char *) &buf) + p[1]);
12304                 s = t / clk_tck;
12305                 out1fmt("%ldm%ld.%.3lds%c",
12306                         s/60, s%60,
12307                         ((t - s * clk_tck) * 1000) / clk_tck,
12308                         p[0]);
12309         } while (*(p += 2));
12310
12311         return 0;
12312 }
12313
12314 #if ENABLE_ASH_MATH_SUPPORT
12315 static arith_t
12316 dash_arith(const char *s)
12317 {
12318         arith_t result;
12319         int errcode = 0;
12320
12321         INT_OFF;
12322         result = arith(s, &errcode);
12323         if (errcode < 0) {
12324                 if (errcode == -3)
12325                         ash_msg_and_raise_error("exponent less than 0");
12326                 if (errcode == -2)
12327                         ash_msg_and_raise_error("divide by zero");
12328                 if (errcode == -5)
12329                         ash_msg_and_raise_error("expression recursion loop detected");
12330                 raise_error_syntax(s);
12331         }
12332         INT_ON;
12333
12334         return result;
12335 }
12336
12337 /*
12338  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12339  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12340  *
12341  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12342  */
12343 static int
12344 letcmd(int argc UNUSED_PARAM, char **argv)
12345 {
12346         arith_t i;
12347
12348         argv++;
12349         if (!*argv)
12350                 ash_msg_and_raise_error("expression expected");
12351         do {
12352                 i = dash_arith(*argv);
12353         } while (*++argv);
12354
12355         return !i;
12356 }
12357 #endif /* ASH_MATH_SUPPORT */
12358
12359
12360 /* ============ miscbltin.c
12361  *
12362  * Miscellaneous builtins.
12363  */
12364
12365 #undef rflag
12366
12367 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12368 typedef enum __rlimit_resource rlim_t;
12369 #endif
12370
12371 /*
12372  * The read builtin. Options:
12373  *      -r              Do not interpret '\' specially
12374  *      -s              Turn off echo (tty only)
12375  *      -n NCHARS       Read NCHARS max
12376  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12377  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12378  *      -u FD           Read from given FD instead of fd 0
12379  * This uses unbuffered input, which may be avoidable in some cases.
12380  * TODO: bash also has:
12381  *      -a ARRAY        Read into array[0],[1],etc
12382  *      -d DELIM        End on DELIM char, not newline
12383  *      -e              Use line editing (tty only)
12384  */
12385 static int
12386 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12387 {
12388         static const char *const arg_REPLY[] = { "REPLY", NULL };
12389
12390         char **ap;
12391         int backslash;
12392         char c;
12393         int rflag;
12394         char *prompt;
12395         const char *ifs;
12396         char *p;
12397         int startword;
12398         int status;
12399         int i;
12400         int fd = 0;
12401 #if ENABLE_ASH_READ_NCHARS
12402         int nchars = 0; /* if != 0, -n is in effect */
12403         int silent = 0;
12404         struct termios tty, old_tty;
12405 #endif
12406 #if ENABLE_ASH_READ_TIMEOUT
12407         unsigned end_ms = 0;
12408         unsigned timeout = 0;
12409 #endif
12410
12411         rflag = 0;
12412         prompt = NULL;
12413         while ((i = nextopt("p:u:r"
12414                 USE_ASH_READ_TIMEOUT("t:")
12415                 USE_ASH_READ_NCHARS("n:s")
12416         )) != '\0') {
12417                 switch (i) {
12418                 case 'p':
12419                         prompt = optionarg;
12420                         break;
12421 #if ENABLE_ASH_READ_NCHARS
12422                 case 'n':
12423                         nchars = bb_strtou(optionarg, NULL, 10);
12424                         if (nchars < 0 || errno)
12425                                 ash_msg_and_raise_error("invalid count");
12426                         /* nchars == 0: off (bash 3.2 does this too) */
12427                         break;
12428                 case 's':
12429                         silent = 1;
12430                         break;
12431 #endif
12432 #if ENABLE_ASH_READ_TIMEOUT
12433                 case 't':
12434                         timeout = bb_strtou(optionarg, NULL, 10);
12435                         if (errno || timeout > UINT_MAX / 2048)
12436                                 ash_msg_and_raise_error("invalid timeout");
12437                         timeout *= 1000;
12438 #if 0 /* even bash have no -t N.NNN support */
12439                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
12440                         ts.tv_usec = 0;
12441                         /* EINVAL means number is ok, but not terminated by NUL */
12442                         if (*p == '.' && errno == EINVAL) {
12443                                 char *p2;
12444                                 if (*++p) {
12445                                         int scale;
12446                                         ts.tv_usec = bb_strtou(p, &p2, 10);
12447                                         if (errno)
12448                                                 ash_msg_and_raise_error("invalid timeout");
12449                                         scale = p2 - p;
12450                                         /* normalize to usec */
12451                                         if (scale > 6)
12452                                                 ash_msg_and_raise_error("invalid timeout");
12453                                         while (scale++ < 6)
12454                                                 ts.tv_usec *= 10;
12455                                 }
12456                         } else if (ts.tv_sec < 0 || errno) {
12457                                 ash_msg_and_raise_error("invalid timeout");
12458                         }
12459                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12460                                 ash_msg_and_raise_error("invalid timeout");
12461                         }
12462 #endif /* if 0 */
12463                         break;
12464 #endif
12465                 case 'r':
12466                         rflag = 1;
12467                         break;
12468                 case 'u':
12469                         fd = bb_strtou(optionarg, NULL, 10);
12470                         if (fd < 0 || errno)
12471                                 ash_msg_and_raise_error("invalid file descriptor");
12472                         break;
12473                 default:
12474                         break;
12475                 }
12476         }
12477         if (prompt && isatty(fd)) {
12478                 out2str(prompt);
12479         }
12480         ap = argptr;
12481         if (*ap == NULL)
12482                 ap = (char**)arg_REPLY;
12483         ifs = bltinlookup("IFS");
12484         if (ifs == NULL)
12485                 ifs = defifs;
12486 #if ENABLE_ASH_READ_NCHARS
12487         tcgetattr(fd, &tty);
12488         old_tty = tty;
12489         if (nchars || silent) {
12490                 if (nchars) {
12491                         tty.c_lflag &= ~ICANON;
12492                         tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12493                 }
12494                 if (silent) {
12495                         tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12496                 }
12497                 /* if tcgetattr failed, tcsetattr will fail too.
12498                  * Ignoring, it's harmless. */
12499                 tcsetattr(fd, TCSANOW, &tty);
12500         }
12501 #endif
12502
12503         status = 0;
12504         startword = 1;
12505         backslash = 0;
12506 #if ENABLE_ASH_READ_TIMEOUT
12507         if (timeout) /* NB: ensuring end_ms is nonzero */
12508                 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12509 #endif
12510         STARTSTACKSTR(p);
12511         do {
12512 #if ENABLE_ASH_READ_TIMEOUT
12513                 if (end_ms) {
12514                         struct pollfd pfd[1];
12515                         pfd[0].fd = fd;
12516                         pfd[0].events = POLLIN;
12517                         timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12518                         if ((int)timeout <= 0 /* already late? */
12519                          || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12520                         ) { /* timed out! */
12521 #if ENABLE_ASH_READ_NCHARS
12522                                 tcsetattr(fd, TCSANOW, &old_tty);
12523 #endif
12524                                 return 1;
12525                         }
12526                 }
12527 #endif
12528                 if (nonblock_safe_read(fd, &c, 1) != 1) {
12529                         status = 1;
12530                         break;
12531                 }
12532                 if (c == '\0')
12533                         continue;
12534                 if (backslash) {
12535                         backslash = 0;
12536                         if (c != '\n')
12537                                 goto put;
12538                         continue;
12539                 }
12540                 if (!rflag && c == '\\') {
12541                         backslash++;
12542                         continue;
12543                 }
12544                 if (c == '\n')
12545                         break;
12546                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12547                         continue;
12548                 }
12549                 startword = 0;
12550                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12551                         STACKSTRNUL(p);
12552                         setvar(*ap, stackblock(), 0);
12553                         ap++;
12554                         startword = 1;
12555                         STARTSTACKSTR(p);
12556                 } else {
12557  put:
12558                         STPUTC(c, p);
12559                 }
12560         }
12561 /* end of do {} while: */
12562 #if ENABLE_ASH_READ_NCHARS
12563         while (--nchars);
12564 #else
12565         while (1);
12566 #endif
12567
12568 #if ENABLE_ASH_READ_NCHARS
12569         tcsetattr(fd, TCSANOW, &old_tty);
12570 #endif
12571
12572         STACKSTRNUL(p);
12573         /* Remove trailing blanks */
12574         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12575                 *p = '\0';
12576         setvar(*ap, stackblock(), 0);
12577         while (*++ap != NULL)
12578                 setvar(*ap, nullstr, 0);
12579         return status;
12580 }
12581
12582 static int
12583 umaskcmd(int argc UNUSED_PARAM, char **argv)
12584 {
12585         static const char permuser[3] ALIGN1 = "ugo";
12586         static const char permmode[3] ALIGN1 = "rwx";
12587         static const short permmask[] ALIGN2 = {
12588                 S_IRUSR, S_IWUSR, S_IXUSR,
12589                 S_IRGRP, S_IWGRP, S_IXGRP,
12590                 S_IROTH, S_IWOTH, S_IXOTH
12591         };
12592
12593         char *ap;
12594         mode_t mask;
12595         int i;
12596         int symbolic_mode = 0;
12597
12598         while (nextopt("S") != '\0') {
12599                 symbolic_mode = 1;
12600         }
12601
12602         INT_OFF;
12603         mask = umask(0);
12604         umask(mask);
12605         INT_ON;
12606
12607         ap = *argptr;
12608         if (ap == NULL) {
12609                 if (symbolic_mode) {
12610                         char buf[18];
12611                         char *p = buf;
12612
12613                         for (i = 0; i < 3; i++) {
12614                                 int j;
12615
12616                                 *p++ = permuser[i];
12617                                 *p++ = '=';
12618                                 for (j = 0; j < 3; j++) {
12619                                         if ((mask & permmask[3 * i + j]) == 0) {
12620                                                 *p++ = permmode[j];
12621                                         }
12622                                 }
12623                                 *p++ = ',';
12624                         }
12625                         *--p = 0;
12626                         puts(buf);
12627                 } else {
12628                         out1fmt("%.4o\n", mask);
12629                 }
12630         } else {
12631                 if (isdigit((unsigned char) *ap)) {
12632                         mask = 0;
12633                         do {
12634                                 if (*ap >= '8' || *ap < '0')
12635                                         ash_msg_and_raise_error(illnum, argv[1]);
12636                                 mask = (mask << 3) + (*ap - '0');
12637                         } while (*++ap != '\0');
12638                         umask(mask);
12639                 } else {
12640                         mask = ~mask & 0777;
12641                         if (!bb_parse_mode(ap, &mask)) {
12642                                 ash_msg_and_raise_error("illegal mode: %s", ap);
12643                         }
12644                         umask(~mask & 0777);
12645                 }
12646         }
12647         return 0;
12648 }
12649
12650 /*
12651  * ulimit builtin
12652  *
12653  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12654  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12655  * ash by J.T. Conklin.
12656  *
12657  * Public domain.
12658  */
12659
12660 struct limits {
12661         uint8_t cmd;          /* RLIMIT_xxx fit into it */
12662         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12663         char    option;
12664 };
12665
12666 static const struct limits limits_tbl[] = {
12667 #ifdef RLIMIT_CPU
12668         { RLIMIT_CPU,        0, 't' },
12669 #endif
12670 #ifdef RLIMIT_FSIZE
12671         { RLIMIT_FSIZE,      9, 'f' },
12672 #endif
12673 #ifdef RLIMIT_DATA
12674         { RLIMIT_DATA,      10, 'd' },
12675 #endif
12676 #ifdef RLIMIT_STACK
12677         { RLIMIT_STACK,     10, 's' },
12678 #endif
12679 #ifdef RLIMIT_CORE
12680         { RLIMIT_CORE,       9, 'c' },
12681 #endif
12682 #ifdef RLIMIT_RSS
12683         { RLIMIT_RSS,       10, 'm' },
12684 #endif
12685 #ifdef RLIMIT_MEMLOCK
12686         { RLIMIT_MEMLOCK,   10, 'l' },
12687 #endif
12688 #ifdef RLIMIT_NPROC
12689         { RLIMIT_NPROC,      0, 'p' },
12690 #endif
12691 #ifdef RLIMIT_NOFILE
12692         { RLIMIT_NOFILE,     0, 'n' },
12693 #endif
12694 #ifdef RLIMIT_AS
12695         { RLIMIT_AS,        10, 'v' },
12696 #endif
12697 #ifdef RLIMIT_LOCKS
12698         { RLIMIT_LOCKS,      0, 'w' },
12699 #endif
12700 };
12701 static const char limits_name[] =
12702 #ifdef RLIMIT_CPU
12703         "time(seconds)" "\0"
12704 #endif
12705 #ifdef RLIMIT_FSIZE
12706         "file(blocks)" "\0"
12707 #endif
12708 #ifdef RLIMIT_DATA
12709         "data(kb)" "\0"
12710 #endif
12711 #ifdef RLIMIT_STACK
12712         "stack(kb)" "\0"
12713 #endif
12714 #ifdef RLIMIT_CORE
12715         "coredump(blocks)" "\0"
12716 #endif
12717 #ifdef RLIMIT_RSS
12718         "memory(kb)" "\0"
12719 #endif
12720 #ifdef RLIMIT_MEMLOCK
12721         "locked memory(kb)" "\0"
12722 #endif
12723 #ifdef RLIMIT_NPROC
12724         "process" "\0"
12725 #endif
12726 #ifdef RLIMIT_NOFILE
12727         "nofiles" "\0"
12728 #endif
12729 #ifdef RLIMIT_AS
12730         "vmemory(kb)" "\0"
12731 #endif
12732 #ifdef RLIMIT_LOCKS
12733         "locks" "\0"
12734 #endif
12735 ;
12736
12737 enum limtype { SOFT = 0x1, HARD = 0x2 };
12738
12739 static void
12740 printlim(enum limtype how, const struct rlimit *limit,
12741                         const struct limits *l)
12742 {
12743         rlim_t val;
12744
12745         val = limit->rlim_max;
12746         if (how & SOFT)
12747                 val = limit->rlim_cur;
12748
12749         if (val == RLIM_INFINITY)
12750                 out1fmt("unlimited\n");
12751         else {
12752                 val >>= l->factor_shift;
12753                 out1fmt("%lld\n", (long long) val);
12754         }
12755 }
12756
12757 static int
12758 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12759 {
12760         int c;
12761         rlim_t val = 0;
12762         enum limtype how = SOFT | HARD;
12763         const struct limits *l;
12764         int set, all = 0;
12765         int optc, what;
12766         struct rlimit limit;
12767
12768         what = 'f';
12769         while ((optc = nextopt("HSa"
12770 #ifdef RLIMIT_CPU
12771                                 "t"
12772 #endif
12773 #ifdef RLIMIT_FSIZE
12774                                 "f"
12775 #endif
12776 #ifdef RLIMIT_DATA
12777                                 "d"
12778 #endif
12779 #ifdef RLIMIT_STACK
12780                                 "s"
12781 #endif
12782 #ifdef RLIMIT_CORE
12783                                 "c"
12784 #endif
12785 #ifdef RLIMIT_RSS
12786                                 "m"
12787 #endif
12788 #ifdef RLIMIT_MEMLOCK
12789                                 "l"
12790 #endif
12791 #ifdef RLIMIT_NPROC
12792                                 "p"
12793 #endif
12794 #ifdef RLIMIT_NOFILE
12795                                 "n"
12796 #endif
12797 #ifdef RLIMIT_AS
12798                                 "v"
12799 #endif
12800 #ifdef RLIMIT_LOCKS
12801                                 "w"
12802 #endif
12803                                         )) != '\0')
12804                 switch (optc) {
12805                 case 'H':
12806                         how = HARD;
12807                         break;
12808                 case 'S':
12809                         how = SOFT;
12810                         break;
12811                 case 'a':
12812                         all = 1;
12813                         break;
12814                 default:
12815                         what = optc;
12816                 }
12817
12818         for (l = limits_tbl; l->option != what; l++)
12819                 continue;
12820
12821         set = *argptr ? 1 : 0;
12822         if (set) {
12823                 char *p = *argptr;
12824
12825                 if (all || argptr[1])
12826                         ash_msg_and_raise_error("too many arguments");
12827                 if (strncmp(p, "unlimited\n", 9) == 0)
12828                         val = RLIM_INFINITY;
12829                 else {
12830                         val = (rlim_t) 0;
12831
12832                         while ((c = *p++) >= '0' && c <= '9') {
12833                                 val = (val * 10) + (long)(c - '0');
12834                                 // val is actually 'unsigned long int' and can't get < 0
12835                                 if (val < (rlim_t) 0)
12836                                         break;
12837                         }
12838                         if (c)
12839                                 ash_msg_and_raise_error("bad number");
12840                         val <<= l->factor_shift;
12841                 }
12842         }
12843         if (all) {
12844                 const char *lname = limits_name;
12845                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12846                         getrlimit(l->cmd, &limit);
12847                         out1fmt("%-20s ", lname);
12848                         lname += strlen(lname) + 1;
12849                         printlim(how, &limit, l);
12850                 }
12851                 return 0;
12852         }
12853
12854         getrlimit(l->cmd, &limit);
12855         if (set) {
12856                 if (how & HARD)
12857                         limit.rlim_max = val;
12858                 if (how & SOFT)
12859                         limit.rlim_cur = val;
12860                 if (setrlimit(l->cmd, &limit) < 0)
12861                         ash_msg_and_raise_error("error setting limit (%m)");
12862         } else {
12863                 printlim(how, &limit, l);
12864         }
12865         return 0;
12866 }
12867
12868
12869 /* ============ Math support */
12870
12871 #if ENABLE_ASH_MATH_SUPPORT
12872
12873 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12874
12875    Permission is hereby granted, free of charge, to any person obtaining
12876    a copy of this software and associated documentation files (the
12877    "Software"), to deal in the Software without restriction, including
12878    without limitation the rights to use, copy, modify, merge, publish,
12879    distribute, sublicense, and/or sell copies of the Software, and to
12880    permit persons to whom the Software is furnished to do so, subject to
12881    the following conditions:
12882
12883    The above copyright notice and this permission notice shall be
12884    included in all copies or substantial portions of the Software.
12885
12886    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12887    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12888    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12889    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12890    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12891    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12892    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12893 */
12894
12895 /* This is my infix parser/evaluator. It is optimized for size, intended
12896  * as a replacement for yacc-based parsers. However, it may well be faster
12897  * than a comparable parser written in yacc. The supported operators are
12898  * listed in #defines below. Parens, order of operations, and error handling
12899  * are supported. This code is thread safe. The exact expression format should
12900  * be that which POSIX specifies for shells. */
12901
12902 /* The code uses a simple two-stack algorithm. See
12903  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12904  * for a detailed explanation of the infix-to-postfix algorithm on which
12905  * this is based (this code differs in that it applies operators immediately
12906  * to the stack instead of adding them to a queue to end up with an
12907  * expression). */
12908
12909 /* To use the routine, call it with an expression string and error return
12910  * pointer */
12911
12912 /*
12913  * Aug 24, 2001              Manuel Novoa III
12914  *
12915  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12916  *
12917  * 1) In arith_apply():
12918  *    a) Cached values of *numptr and &(numptr[-1]).
12919  *    b) Removed redundant test for zero denominator.
12920  *
12921  * 2) In arith():
12922  *    a) Eliminated redundant code for processing operator tokens by moving
12923  *       to a table-based implementation.  Also folded handling of parens
12924  *       into the table.
12925  *    b) Combined all 3 loops which called arith_apply to reduce generated
12926  *       code size at the cost of speed.
12927  *
12928  * 3) The following expressions were treated as valid by the original code:
12929  *       1()  ,    0!  ,    1 ( *3 )   .
12930  *    These bugs have been fixed by internally enclosing the expression in
12931  *    parens and then checking that all binary ops and right parens are
12932  *    preceded by a valid expression (NUM_TOKEN).
12933  *
12934  * Note: It may be desirable to replace Aaron's test for whitespace with
12935  * ctype's isspace() if it is used by another busybox applet or if additional
12936  * whitespace chars should be considered.  Look below the "#include"s for a
12937  * precompiler test.
12938  */
12939
12940 /*
12941  * Aug 26, 2001              Manuel Novoa III
12942  *
12943  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12944  *
12945  * Merge in Aaron's comments previously posted to the busybox list,
12946  * modified slightly to take account of my changes to the code.
12947  *
12948  */
12949
12950 /*
12951  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12952  *
12953  * - allow access to variable,
12954  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12955  * - realize assign syntax (VAR=expr, +=, *= etc)
12956  * - realize exponentiation (** operator)
12957  * - realize comma separated - expr, expr
12958  * - realise ++expr --expr expr++ expr--
12959  * - realise expr ? expr : expr (but, second expr calculate always)
12960  * - allow hexadecimal and octal numbers
12961  * - was restored loses XOR operator
12962  * - remove one goto label, added three ;-)
12963  * - protect $((num num)) as true zero expr (Manuel`s error)
12964  * - always use special isspace(), see comment from bash ;-)
12965  */
12966
12967 #define arith_isspace(arithval) \
12968         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12969
12970 typedef unsigned char operator;
12971
12972 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12973  * precedence, and 3 high bits are an ID unique across operators of that
12974  * precedence. The ID portion is so that multiple operators can have the
12975  * same precedence, ensuring that the leftmost one is evaluated first.
12976  * Consider * and /. */
12977
12978 #define tok_decl(prec,id) (((id)<<5)|(prec))
12979 #define PREC(op) ((op) & 0x1F)
12980
12981 #define TOK_LPAREN tok_decl(0,0)
12982
12983 #define TOK_COMMA tok_decl(1,0)
12984
12985 #define TOK_ASSIGN tok_decl(2,0)
12986 #define TOK_AND_ASSIGN tok_decl(2,1)
12987 #define TOK_OR_ASSIGN tok_decl(2,2)
12988 #define TOK_XOR_ASSIGN tok_decl(2,3)
12989 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12990 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12991 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12992 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12993
12994 #define TOK_MUL_ASSIGN tok_decl(3,0)
12995 #define TOK_DIV_ASSIGN tok_decl(3,1)
12996 #define TOK_REM_ASSIGN tok_decl(3,2)
12997
12998 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12999 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
13000
13001 /* conditional is right associativity too */
13002 #define TOK_CONDITIONAL tok_decl(4,0)
13003 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13004
13005 #define TOK_OR tok_decl(5,0)
13006
13007 #define TOK_AND tok_decl(6,0)
13008
13009 #define TOK_BOR tok_decl(7,0)
13010
13011 #define TOK_BXOR tok_decl(8,0)
13012
13013 #define TOK_BAND tok_decl(9,0)
13014
13015 #define TOK_EQ tok_decl(10,0)
13016 #define TOK_NE tok_decl(10,1)
13017
13018 #define TOK_LT tok_decl(11,0)
13019 #define TOK_GT tok_decl(11,1)
13020 #define TOK_GE tok_decl(11,2)
13021 #define TOK_LE tok_decl(11,3)
13022
13023 #define TOK_LSHIFT tok_decl(12,0)
13024 #define TOK_RSHIFT tok_decl(12,1)
13025
13026 #define TOK_ADD tok_decl(13,0)
13027 #define TOK_SUB tok_decl(13,1)
13028
13029 #define TOK_MUL tok_decl(14,0)
13030 #define TOK_DIV tok_decl(14,1)
13031 #define TOK_REM tok_decl(14,2)
13032
13033 /* exponent is right associativity */
13034 #define TOK_EXPONENT tok_decl(15,1)
13035
13036 /* For now unary operators. */
13037 #define UNARYPREC 16
13038 #define TOK_BNOT tok_decl(UNARYPREC,0)
13039 #define TOK_NOT tok_decl(UNARYPREC,1)
13040
13041 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13042 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13043
13044 #define PREC_PRE (UNARYPREC+2)
13045
13046 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13047 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13048
13049 #define PREC_POST (UNARYPREC+3)
13050
13051 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13052 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13053
13054 #define SPEC_PREC (UNARYPREC+4)
13055
13056 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13057 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13058
13059 #define NUMPTR (*numstackptr)
13060
13061 static int
13062 tok_have_assign(operator op)
13063 {
13064         operator prec = PREC(op);
13065
13066         convert_prec_is_assing(prec);
13067         return (prec == PREC(TOK_ASSIGN) ||
13068                         prec == PREC_PRE || prec == PREC_POST);
13069 }
13070
13071 static int
13072 is_right_associativity(operator prec)
13073 {
13074         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13075                 || prec == PREC(TOK_CONDITIONAL));
13076 }
13077
13078 typedef struct {
13079         arith_t val;
13080         arith_t contidional_second_val;
13081         char contidional_second_val_initialized;
13082         char *var;      /* if NULL then is regular number,
13083                            else is variable name */
13084 } v_n_t;
13085
13086 typedef struct chk_var_recursive_looped_t {
13087         const char *var;
13088         struct chk_var_recursive_looped_t *next;
13089 } chk_var_recursive_looped_t;
13090
13091 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13092
13093 static int
13094 arith_lookup_val(v_n_t *t)
13095 {
13096         if (t->var) {
13097                 const char * p = lookupvar(t->var);
13098
13099                 if (p) {
13100                         int errcode;
13101
13102                         /* recursive try as expression */
13103                         chk_var_recursive_looped_t *cur;
13104                         chk_var_recursive_looped_t cur_save;
13105
13106                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13107                                 if (strcmp(cur->var, t->var) == 0) {
13108                                         /* expression recursion loop detected */
13109                                         return -5;
13110                                 }
13111                         }
13112                         /* save current lookuped var name */
13113                         cur = prev_chk_var_recursive;
13114                         cur_save.var = t->var;
13115                         cur_save.next = cur;
13116                         prev_chk_var_recursive = &cur_save;
13117
13118                         t->val = arith (p, &errcode);
13119                         /* restore previous ptr after recursiving */
13120                         prev_chk_var_recursive = cur;
13121                         return errcode;
13122                 }
13123                 /* allow undefined var as 0 */
13124                 t->val = 0;
13125         }
13126         return 0;
13127 }
13128
13129 /* "applying" a token means performing it on the top elements on the integer
13130  * stack. For a unary operator it will only change the top element, but a
13131  * binary operator will pop two arguments and push a result */
13132 static int
13133 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13134 {
13135         v_n_t *numptr_m1;
13136         arith_t numptr_val, rez;
13137         int ret_arith_lookup_val;
13138
13139         /* There is no operator that can work without arguments */
13140         if (NUMPTR == numstack) goto err;
13141         numptr_m1 = NUMPTR - 1;
13142
13143         /* check operand is var with noninteger value */
13144         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13145         if (ret_arith_lookup_val)
13146                 return ret_arith_lookup_val;
13147
13148         rez = numptr_m1->val;
13149         if (op == TOK_UMINUS)
13150                 rez *= -1;
13151         else if (op == TOK_NOT)
13152                 rez = !rez;
13153         else if (op == TOK_BNOT)
13154                 rez = ~rez;
13155         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13156                 rez++;
13157         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13158                 rez--;
13159         else if (op != TOK_UPLUS) {
13160                 /* Binary operators */
13161
13162                 /* check and binary operators need two arguments */
13163                 if (numptr_m1 == numstack) goto err;
13164
13165                 /* ... and they pop one */
13166                 --NUMPTR;
13167                 numptr_val = rez;
13168                 if (op == TOK_CONDITIONAL) {
13169                         if (!numptr_m1->contidional_second_val_initialized) {
13170                                 /* protect $((expr1 ? expr2)) without ": expr" */
13171                                 goto err;
13172                         }
13173                         rez = numptr_m1->contidional_second_val;
13174                 } else if (numptr_m1->contidional_second_val_initialized) {
13175                         /* protect $((expr1 : expr2)) without "expr ? " */
13176                         goto err;
13177                 }
13178                 numptr_m1 = NUMPTR - 1;
13179                 if (op != TOK_ASSIGN) {
13180                         /* check operand is var with noninteger value for not '=' */
13181                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13182                         if (ret_arith_lookup_val)
13183                                 return ret_arith_lookup_val;
13184                 }
13185                 if (op == TOK_CONDITIONAL) {
13186                         numptr_m1->contidional_second_val = rez;
13187                 }
13188                 rez = numptr_m1->val;
13189                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13190                         rez |= numptr_val;
13191                 else if (op == TOK_OR)
13192                         rez = numptr_val || rez;
13193                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13194                         rez &= numptr_val;
13195                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13196                         rez ^= numptr_val;
13197                 else if (op == TOK_AND)
13198                         rez = rez && numptr_val;
13199                 else if (op == TOK_EQ)
13200                         rez = (rez == numptr_val);
13201                 else if (op == TOK_NE)
13202                         rez = (rez != numptr_val);
13203                 else if (op == TOK_GE)
13204                         rez = (rez >= numptr_val);
13205                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13206                         rez >>= numptr_val;
13207                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13208                         rez <<= numptr_val;
13209                 else if (op == TOK_GT)
13210                         rez = (rez > numptr_val);
13211                 else if (op == TOK_LT)
13212                         rez = (rez < numptr_val);
13213                 else if (op == TOK_LE)
13214                         rez = (rez <= numptr_val);
13215                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13216                         rez *= numptr_val;
13217                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13218                         rez += numptr_val;
13219                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13220                         rez -= numptr_val;
13221                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13222                         rez = numptr_val;
13223                 else if (op == TOK_CONDITIONAL_SEP) {
13224                         if (numptr_m1 == numstack) {
13225                                 /* protect $((expr : expr)) without "expr ? " */
13226                                 goto err;
13227                         }
13228                         numptr_m1->contidional_second_val_initialized = op;
13229                         numptr_m1->contidional_second_val = numptr_val;
13230                 } else if (op == TOK_CONDITIONAL) {
13231                         rez = rez ?
13232                                 numptr_val : numptr_m1->contidional_second_val;
13233                 } else if (op == TOK_EXPONENT) {
13234                         if (numptr_val < 0)
13235                                 return -3;      /* exponent less than 0 */
13236                         else {
13237                                 arith_t c = 1;
13238
13239                                 if (numptr_val)
13240                                         while (numptr_val--)
13241                                                 c *= rez;
13242                                 rez = c;
13243                         }
13244                 } else if (numptr_val==0)          /* zero divisor check */
13245                         return -2;
13246                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13247                         rez /= numptr_val;
13248                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13249                         rez %= numptr_val;
13250         }
13251         if (tok_have_assign(op)) {
13252                 char buf[sizeof(arith_t_type)*3 + 2];
13253
13254                 if (numptr_m1->var == NULL) {
13255                         /* Hmm, 1=2 ? */
13256                         goto err;
13257                 }
13258                 /* save to shell variable */
13259 #if ENABLE_ASH_MATH_SUPPORT_64
13260                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13261 #else
13262                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13263 #endif
13264                 setvar(numptr_m1->var, buf, 0);
13265                 /* after saving, make previous value for v++ or v-- */
13266                 if (op == TOK_POST_INC)
13267                         rez--;
13268                 else if (op == TOK_POST_DEC)
13269                         rez++;
13270         }
13271         numptr_m1->val = rez;
13272         /* protect geting var value, is number now */
13273         numptr_m1->var = NULL;
13274         return 0;
13275  err:
13276         return -1;
13277 }
13278
13279 /* longest must be first */
13280 static const char op_tokens[] ALIGN1 = {
13281         '<','<','=',0, TOK_LSHIFT_ASSIGN,
13282         '>','>','=',0, TOK_RSHIFT_ASSIGN,
13283         '<','<',    0, TOK_LSHIFT,
13284         '>','>',    0, TOK_RSHIFT,
13285         '|','|',    0, TOK_OR,
13286         '&','&',    0, TOK_AND,
13287         '!','=',    0, TOK_NE,
13288         '<','=',    0, TOK_LE,
13289         '>','=',    0, TOK_GE,
13290         '=','=',    0, TOK_EQ,
13291         '|','=',    0, TOK_OR_ASSIGN,
13292         '&','=',    0, TOK_AND_ASSIGN,
13293         '*','=',    0, TOK_MUL_ASSIGN,
13294         '/','=',    0, TOK_DIV_ASSIGN,
13295         '%','=',    0, TOK_REM_ASSIGN,
13296         '+','=',    0, TOK_PLUS_ASSIGN,
13297         '-','=',    0, TOK_MINUS_ASSIGN,
13298         '-','-',    0, TOK_POST_DEC,
13299         '^','=',    0, TOK_XOR_ASSIGN,
13300         '+','+',    0, TOK_POST_INC,
13301         '*','*',    0, TOK_EXPONENT,
13302         '!',        0, TOK_NOT,
13303         '<',        0, TOK_LT,
13304         '>',        0, TOK_GT,
13305         '=',        0, TOK_ASSIGN,
13306         '|',        0, TOK_BOR,
13307         '&',        0, TOK_BAND,
13308         '*',        0, TOK_MUL,
13309         '/',        0, TOK_DIV,
13310         '%',        0, TOK_REM,
13311         '+',        0, TOK_ADD,
13312         '-',        0, TOK_SUB,
13313         '^',        0, TOK_BXOR,
13314         /* uniq */
13315         '~',        0, TOK_BNOT,
13316         ',',        0, TOK_COMMA,
13317         '?',        0, TOK_CONDITIONAL,
13318         ':',        0, TOK_CONDITIONAL_SEP,
13319         ')',        0, TOK_RPAREN,
13320         '(',        0, TOK_LPAREN,
13321         0
13322 };
13323 /* ptr to ")" */
13324 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13325
13326 static arith_t
13327 arith(const char *expr, int *perrcode)
13328 {
13329         char arithval; /* Current character under analysis */
13330         operator lasttok, op;
13331         operator prec;
13332         operator *stack, *stackptr;
13333         const char *p = endexpression;
13334         int errcode;
13335         v_n_t *numstack, *numstackptr;
13336         unsigned datasizes = strlen(expr) + 2;
13337
13338         /* Stack of integers */
13339         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13340          * in any given correct or incorrect expression is left as an exercise to
13341          * the reader. */
13342         numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13343         /* Stack of operator tokens */
13344         stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13345
13346         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
13347         *perrcode = errcode = 0;
13348
13349         while (1) {
13350                 arithval = *expr;
13351                 if (arithval == 0) {
13352                         if (p == endexpression) {
13353                                 /* Null expression. */
13354                                 return 0;
13355                         }
13356
13357                         /* This is only reached after all tokens have been extracted from the
13358                          * input stream. If there are still tokens on the operator stack, they
13359                          * are to be applied in order. At the end, there should be a final
13360                          * result on the integer stack */
13361
13362                         if (expr != endexpression + 1) {
13363                                 /* If we haven't done so already, */
13364                                 /* append a closing right paren */
13365                                 expr = endexpression;
13366                                 /* and let the loop process it. */
13367                                 continue;
13368                         }
13369                         /* At this point, we're done with the expression. */
13370                         if (numstackptr != numstack+1) {
13371                                 /* ... but if there isn't, it's bad */
13372  err:
13373                                 *perrcode = -1;
13374                                 return *perrcode;
13375                         }
13376                         if (numstack->var) {
13377                                 /* expression is $((var)) only, lookup now */
13378                                 errcode = arith_lookup_val(numstack);
13379                         }
13380  ret:
13381                         *perrcode = errcode;
13382                         return numstack->val;
13383                 }
13384
13385                 /* Continue processing the expression. */
13386                 if (arith_isspace(arithval)) {
13387                         /* Skip whitespace */
13388                         goto prologue;
13389                 }
13390                 p = endofname(expr);
13391                 if (p != expr) {
13392                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
13393
13394                         numstackptr->var = alloca(var_name_size);
13395                         safe_strncpy(numstackptr->var, expr, var_name_size);
13396                         expr = p;
13397  num:
13398                         numstackptr->contidional_second_val_initialized = 0;
13399                         numstackptr++;
13400                         lasttok = TOK_NUM;
13401                         continue;
13402                 }
13403                 if (isdigit(arithval)) {
13404                         numstackptr->var = NULL;
13405 #if ENABLE_ASH_MATH_SUPPORT_64
13406                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
13407 #else
13408                         numstackptr->val = strtol(expr, (char **) &expr, 0);
13409 #endif
13410                         goto num;
13411                 }
13412                 for (p = op_tokens; ; p++) {
13413                         const char *o;
13414
13415                         if (*p == 0) {
13416                                 /* strange operator not found */
13417                                 goto err;
13418                         }
13419                         for (o = expr; *p && *o == *p; p++)
13420                                 o++;
13421                         if (!*p) {
13422                                 /* found */
13423                                 expr = o - 1;
13424                                 break;
13425                         }
13426                         /* skip tail uncompared token */
13427                         while (*p)
13428                                 p++;
13429                         /* skip zero delim */
13430                         p++;
13431                 }
13432                 op = p[1];
13433
13434                 /* post grammar: a++ reduce to num */
13435                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13436                         lasttok = TOK_NUM;
13437
13438                 /* Plus and minus are binary (not unary) _only_ if the last
13439                  * token was as number, or a right paren (which pretends to be
13440                  * a number, since it evaluates to one). Think about it.
13441                  * It makes sense. */
13442                 if (lasttok != TOK_NUM) {
13443                         switch (op) {
13444                         case TOK_ADD:
13445                                 op = TOK_UPLUS;
13446                                 break;
13447                         case TOK_SUB:
13448                                 op = TOK_UMINUS;
13449                                 break;
13450                         case TOK_POST_INC:
13451                                 op = TOK_PRE_INC;
13452                                 break;
13453                         case TOK_POST_DEC:
13454                                 op = TOK_PRE_DEC;
13455                                 break;
13456                         }
13457                 }
13458                 /* We don't want a unary operator to cause recursive descent on the
13459                  * stack, because there can be many in a row and it could cause an
13460                  * operator to be evaluated before its argument is pushed onto the
13461                  * integer stack. */
13462                 /* But for binary operators, "apply" everything on the operator
13463                  * stack until we find an operator with a lesser priority than the
13464                  * one we have just extracted. */
13465                 /* Left paren is given the lowest priority so it will never be
13466                  * "applied" in this way.
13467                  * if associativity is right and priority eq, applied also skip
13468                  */
13469                 prec = PREC(op);
13470                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13471                         /* not left paren or unary */
13472                         if (lasttok != TOK_NUM) {
13473                                 /* binary op must be preceded by a num */
13474                                 goto err;
13475                         }
13476                         while (stackptr != stack) {
13477                                 if (op == TOK_RPAREN) {
13478                                         /* The algorithm employed here is simple: while we don't
13479                                          * hit an open paren nor the bottom of the stack, pop
13480                                          * tokens and apply them */
13481                                         if (stackptr[-1] == TOK_LPAREN) {
13482                                                 --stackptr;
13483                                                 /* Any operator directly after a */
13484                                                 lasttok = TOK_NUM;
13485                                                 /* close paren should consider itself binary */
13486                                                 goto prologue;
13487                                         }
13488                                 } else {
13489                                         operator prev_prec = PREC(stackptr[-1]);
13490
13491                                         convert_prec_is_assing(prec);
13492                                         convert_prec_is_assing(prev_prec);
13493                                         if (prev_prec < prec)
13494                                                 break;
13495                                         /* check right assoc */
13496                                         if (prev_prec == prec && is_right_associativity(prec))
13497                                                 break;
13498                                 }
13499                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13500                                 if (errcode) goto ret;
13501                         }
13502                         if (op == TOK_RPAREN) {
13503                                 goto err;
13504                         }
13505                 }
13506
13507                 /* Push this operator to the stack and remember it. */
13508                 *stackptr++ = lasttok = op;
13509  prologue:
13510                 ++expr;
13511         } /* while */
13512 }
13513 #endif /* ASH_MATH_SUPPORT */
13514
13515
13516 /* ============ main() and helpers */
13517
13518 /*
13519  * Called to exit the shell.
13520  */
13521 static void exitshell(void) NORETURN;
13522 static void
13523 exitshell(void)
13524 {
13525         struct jmploc loc;
13526         char *p;
13527         int status;
13528
13529         status = exitstatus;
13530         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13531         if (setjmp(loc.loc)) {
13532                 if (exception_type == EXEXIT)
13533 /* dash bug: it just does _exit(exitstatus) here
13534  * but we have to do setjobctl(0) first!
13535  * (bug is still not fixed in dash-0.5.3 - if you run dash
13536  * under Midnight Commander, on exit from dash MC is backgrounded) */
13537                         status = exitstatus;
13538                 goto out;
13539         }
13540         exception_handler = &loc;
13541         p = trap[0];
13542         if (p) {
13543                 trap[0] = NULL;
13544                 evalstring(p, 0);
13545         }
13546         flush_stdout_stderr();
13547  out:
13548         setjobctl(0);
13549         _exit(status);
13550         /* NOTREACHED */
13551 }
13552
13553 static void
13554 init(void)
13555 {
13556         /* from input.c: */
13557         basepf.next_to_pgetc = basepf.buf = basebuf;
13558
13559         /* from trap.c: */
13560         signal(SIGCHLD, SIG_DFL);
13561
13562         /* from var.c: */
13563         {
13564                 char **envp;
13565                 char ppid[sizeof(int)*3 + 1];
13566                 const char *p;
13567                 struct stat st1, st2;
13568
13569                 initvar();
13570                 for (envp = environ; envp && *envp; envp++) {
13571                         if (strchr(*envp, '=')) {
13572                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13573                         }
13574                 }
13575
13576                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13577                 setvar("PPID", ppid, 0);
13578
13579                 p = lookupvar("PWD");
13580                 if (p)
13581                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13582                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13583                                 p = '\0';
13584                 setpwd(p, 0);
13585         }
13586 }
13587
13588 /*
13589  * Process the shell command line arguments.
13590  */
13591 static void
13592 procargs(char **argv)
13593 {
13594         int i;
13595         const char *xminusc;
13596         char **xargv;
13597
13598         xargv = argv;
13599         arg0 = xargv[0];
13600         /* if (xargv[0]) - mmm, this is always true! */
13601                 xargv++;
13602         for (i = 0; i < NOPTS; i++)
13603                 optlist[i] = 2;
13604         argptr = xargv;
13605         if (options(1)) {
13606                 /* it already printed err message */
13607                 raise_exception(EXERROR);
13608         }
13609         xargv = argptr;
13610         xminusc = minusc;
13611         if (*xargv == NULL) {
13612                 if (xminusc)
13613                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13614                 sflag = 1;
13615         }
13616         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13617                 iflag = 1;
13618         if (mflag == 2)
13619                 mflag = iflag;
13620         for (i = 0; i < NOPTS; i++)
13621                 if (optlist[i] == 2)
13622                         optlist[i] = 0;
13623 #if DEBUG == 2
13624         debug = 1;
13625 #endif
13626         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13627         if (xminusc) {
13628                 minusc = *xargv++;
13629                 if (*xargv)
13630                         goto setarg0;
13631         } else if (!sflag) {
13632                 setinputfile(*xargv, 0);
13633  setarg0:
13634                 arg0 = *xargv++;
13635                 commandname = arg0;
13636         }
13637
13638         shellparam.p = xargv;
13639 #if ENABLE_ASH_GETOPTS
13640         shellparam.optind = 1;
13641         shellparam.optoff = -1;
13642 #endif
13643         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13644         while (*xargv) {
13645                 shellparam.nparam++;
13646                 xargv++;
13647         }
13648         optschanged();
13649 }
13650
13651 /*
13652  * Read /etc/profile or .profile.
13653  */
13654 static void
13655 read_profile(const char *name)
13656 {
13657         int skip;
13658
13659         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13660                 return;
13661         skip = cmdloop(0);
13662         popfile();
13663         if (skip)
13664                 exitshell();
13665 }
13666
13667 /*
13668  * This routine is called when an error or an interrupt occurs in an
13669  * interactive shell and control is returned to the main command loop.
13670  */
13671 static void
13672 reset(void)
13673 {
13674         /* from eval.c: */
13675         evalskip = 0;
13676         loopnest = 0;
13677         /* from input.c: */
13678         g_parsefile->left_in_buffer = 0;
13679         g_parsefile->left_in_line = 0;      /* clear input buffer */
13680         popallfiles();
13681         /* from parser.c: */
13682         tokpushback = 0;
13683         checkkwd = 0;
13684         /* from redir.c: */
13685         clearredir(/*drop:*/ 0);
13686 }
13687
13688 #if PROFILE
13689 static short profile_buf[16384];
13690 extern int etext();
13691 #endif
13692
13693 /*
13694  * Main routine.  We initialize things, parse the arguments, execute
13695  * profiles if we're a login shell, and then call cmdloop to execute
13696  * commands.  The setjmp call sets up the location to jump to when an
13697  * exception occurs.  When an exception occurs the variable "state"
13698  * is used to figure out how far we had gotten.
13699  */
13700 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13701 int ash_main(int argc UNUSED_PARAM, char **argv)
13702 {
13703         char *shinit;
13704         volatile smallint state;
13705         struct jmploc jmploc;
13706         struct stackmark smark;
13707
13708         /* Initialize global data */
13709         INIT_G_misc();
13710         INIT_G_memstack();
13711         INIT_G_var();
13712 #if ENABLE_ASH_ALIAS
13713         INIT_G_alias();
13714 #endif
13715         INIT_G_cmdtable();
13716
13717 #if PROFILE
13718         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13719 #endif
13720
13721 #if ENABLE_FEATURE_EDITING
13722         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13723 #endif
13724         state = 0;
13725         if (setjmp(jmploc.loc)) {
13726                 smallint e;
13727                 smallint s;
13728
13729                 reset();
13730
13731                 e = exception_type;
13732                 if (e == EXERROR)
13733                         exitstatus = 2;
13734                 s = state;
13735                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13736                         exitshell();
13737                 if (e == EXINT)
13738                         outcslow('\n', stderr);
13739
13740                 popstackmark(&smark);
13741                 FORCE_INT_ON; /* enable interrupts */
13742                 if (s == 1)
13743                         goto state1;
13744                 if (s == 2)
13745                         goto state2;
13746                 if (s == 3)
13747                         goto state3;
13748                 goto state4;
13749         }
13750         exception_handler = &jmploc;
13751 #if DEBUG
13752         opentrace();
13753         trace_puts("Shell args: ");
13754         trace_puts_args(argv);
13755 #endif
13756         rootpid = getpid();
13757
13758 #if ENABLE_ASH_RANDOM_SUPPORT
13759         /* Can use monotonic_ns() for better randomness but for now it is
13760          * not used anywhere else in busybox... so avoid bloat */
13761         random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13762 #endif
13763         init();
13764         setstackmark(&smark);
13765         procargs(argv);
13766
13767 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13768         if (iflag) {
13769                 const char *hp = lookupvar("HISTFILE");
13770
13771                 if (hp == NULL) {
13772                         hp = lookupvar("HOME");
13773                         if (hp != NULL) {
13774                                 char *defhp = concat_path_file(hp, ".ash_history");
13775                                 setvar("HISTFILE", defhp, 0);
13776                                 free(defhp);
13777                         }
13778                 }
13779         }
13780 #endif
13781         if (/* argv[0] && */ argv[0][0] == '-')
13782                 isloginsh = 1;
13783         if (isloginsh) {
13784                 state = 1;
13785                 read_profile("/etc/profile");
13786  state1:
13787                 state = 2;
13788                 read_profile(".profile");
13789         }
13790  state2:
13791         state = 3;
13792         if (
13793 #ifndef linux
13794          getuid() == geteuid() && getgid() == getegid() &&
13795 #endif
13796          iflag
13797         ) {
13798                 shinit = lookupvar("ENV");
13799                 if (shinit != NULL && *shinit != '\0') {
13800                         read_profile(shinit);
13801                 }
13802         }
13803  state3:
13804         state = 4;
13805         if (minusc) {
13806                 /* evalstring pushes parsefile stack.
13807                  * Ensure we don't falsely claim that 0 (stdin)
13808                  * is one of stacked source fds */
13809                 if (!sflag)
13810                         g_parsefile->fd = -1;
13811                 evalstring(minusc, 0);
13812         }
13813
13814         if (sflag || minusc == NULL) {
13815 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13816                 if (iflag) {
13817                         const char *hp = lookupvar("HISTFILE");
13818                         if (hp)
13819                                 line_input_state->hist_file = hp;
13820                 }
13821 #endif
13822  state4: /* XXX ??? - why isn't this before the "if" statement */
13823                 cmdloop(1);
13824         }
13825 #if PROFILE
13826         monitor(0);
13827 #endif
13828 #ifdef GPROF
13829         {
13830                 extern void _mcleanup(void);
13831                 _mcleanup();
13832         }
13833 #endif
13834         exitshell();
13835         /* NOTREACHED */
13836 }
13837
13838 #if DEBUG
13839 const char *applet_name = "debug stuff usage";
13840 int main(int argc, char **argv)
13841 {
13842         return ash_main(argc, argv);
13843 }
13844 #endif
13845
13846
13847 /*-
13848  * Copyright (c) 1989, 1991, 1993, 1994
13849  *      The Regents of the University of California.  All rights reserved.
13850  *
13851  * This code is derived from software contributed to Berkeley by
13852  * Kenneth Almquist.
13853  *
13854  * Redistribution and use in source and binary forms, with or without
13855  * modification, are permitted provided that the following conditions
13856  * are met:
13857  * 1. Redistributions of source code must retain the above copyright
13858  *    notice, this list of conditions and the following disclaimer.
13859  * 2. Redistributions in binary form must reproduce the above copyright
13860  *    notice, this list of conditions and the following disclaimer in the
13861  *    documentation and/or other materials provided with the distribution.
13862  * 3. Neither the name of the University nor the names of its contributors
13863  *    may be used to endorse or promote products derived from this software
13864  *    without specific prior written permission.
13865  *
13866  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13867  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13868  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13869  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13870  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13871  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13872  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13873  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13874  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13875  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13876  * SUCH DAMAGE.
13877  */