ash: fix CONFIG_ASH_OPTIMIZE_FOR_SIZE off + high-bit chars case
[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; /* kind of exception (0..5) */
169         /* exceptions */
170 #define EXINT 0         /* SIGINT received */
171 #define EXERROR 1       /* a generic error */
172 #define EXSHELLPROC 2   /* execute a shell procedure */
173 #define EXEXEC 3        /* command execution failed */
174 #define EXEXIT 4        /* exit the shell */
175 #define EXSIG 5         /* trapped signal in wait(1) */
176
177         smallint isloginsh;
178         char nullstr[1];        /* zero length string */
179
180         char optlist[NOPTS];
181 #define eflag optlist[0]
182 #define fflag optlist[1]
183 #define Iflag optlist[2]
184 #define iflag optlist[3]
185 #define mflag optlist[4]
186 #define nflag optlist[5]
187 #define sflag optlist[6]
188 #define xflag optlist[7]
189 #define vflag optlist[8]
190 #define Cflag optlist[9]
191 #define aflag optlist[10]
192 #define bflag optlist[11]
193 #define uflag optlist[12]
194 #define viflag optlist[13]
195 #if DEBUG
196 #define nolog optlist[14]
197 #define debug optlist[15]
198 #endif
199
200         /* trap handler commands */
201         /*
202          * Sigmode records the current value of the signal handlers for the various
203          * modes.  A value of zero means that the current handler is not known.
204          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
205          */
206         char sigmode[NSIG - 1];
207 #define S_DFL      1            /* default signal handling (SIG_DFL) */
208 #define S_CATCH    2            /* signal is caught */
209 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
210 #define S_HARD_IGN 4            /* signal is ignored permenantly */
211
212         /* indicates specified signal received */
213         char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
214         char *trap[NSIG];
215
216         /* Rarely referenced stuff */
217 #if ENABLE_ASH_RANDOM_SUPPORT
218         /* Random number generators */
219         int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
220         uint32_t random_LCG;        /* LCG (fast but weak) */
221 #endif
222         pid_t backgndpid;        /* pid of last background process */
223         smallint job_warning;    /* user was warned about stopped jobs (can be 2, 1 or 0). */
224 };
225 extern struct globals_misc *const ash_ptr_to_globals_misc;
226 #define G_misc (*ash_ptr_to_globals_misc)
227 #define rootpid     (G_misc.rootpid    )
228 #define shlvl       (G_misc.shlvl      )
229 #define minusc      (G_misc.minusc     )
230 #define curdir      (G_misc.curdir     )
231 #define physdir     (G_misc.physdir    )
232 #define arg0        (G_misc.arg0       )
233 #define exception_handler (G_misc.exception_handler)
234 #define exception         (G_misc.exception        )
235 #define suppressint       (G_misc.suppressint      )
236 #define intpending        (G_misc.intpending       )
237 //#define exsig             (G_misc.exsig            )
238 #define pendingsig        (G_misc.pendingsig       )
239 #define isloginsh   (G_misc.isloginsh  )
240 #define nullstr     (G_misc.nullstr    )
241 #define optlist     (G_misc.optlist    )
242 #define sigmode     (G_misc.sigmode    )
243 #define gotsig      (G_misc.gotsig     )
244 #define trap        (G_misc.trap       )
245 #define random_galois_LFSR (G_misc.random_galois_LFSR)
246 #define random_LCG         (G_misc.random_LCG        )
247 #define backgndpid  (G_misc.backgndpid )
248 #define job_warning (G_misc.job_warning)
249 #define INIT_G_misc() do { \
250         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
251         barrier(); \
252         curdir = nullstr; \
253         physdir = nullstr; \
254 } while (0)
255
256
257 /* ============ Utility functions */
258 static int isdigit_str9(const char *str)
259 {
260         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
261         while (--maxlen && isdigit(*str))
262                 str++;
263         return (*str == '\0');
264 }
265
266
267 /* ============ Interrupts / exceptions */
268 /*
269  * These macros allow the user to suspend the handling of interrupt signals
270  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
271  * much more efficient and portable.  (But hacking the kernel is so much
272  * more fun than worrying about efficiency and portability. :-))
273  */
274 #define INT_OFF do { \
275         suppressint++; \
276         xbarrier(); \
277 } while (0)
278
279 /*
280  * Called to raise an exception.  Since C doesn't include exceptions, we
281  * just do a longjmp to the exception handler.  The type of exception is
282  * stored in the global variable "exception".
283  */
284 static void raise_exception(int) NORETURN;
285 static void
286 raise_exception(int e)
287 {
288 #if DEBUG
289         if (exception_handler == NULL)
290                 abort();
291 #endif
292         INT_OFF;
293         exception = e;
294         longjmp(exception_handler->loc, 1);
295 }
296
297 /*
298  * Called from trap.c when a SIGINT is received.  (If the user specifies
299  * that SIGINT is to be trapped or ignored using the trap builtin, then
300  * this routine is not called.)  Suppressint is nonzero when interrupts
301  * are held using the INT_OFF macro.  (The test for iflag is just
302  * defensive programming.)
303  */
304 static void raise_interrupt(void) NORETURN;
305 static void
306 raise_interrupt(void)
307 {
308         int i;
309
310         intpending = 0;
311         /* Signal is not automatically unmasked after it is raised,
312          * do it ourself - unmask all signals */
313         sigprocmask_allsigs(SIG_UNBLOCK);
314         /* pendingsig = 0; - now done in onsig() */
315
316         i = EXSIG;
317         if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
318                 if (!(rootshell && iflag)) {
319                         /* Kill ourself with SIGINT */
320                         signal(SIGINT, SIG_DFL);
321                         raise(SIGINT);
322                 }
323                 i = EXINT;
324         }
325         raise_exception(i);
326         /* NOTREACHED */
327 }
328
329 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
330 static void
331 int_on(void)
332 {
333         if (--suppressint == 0 && intpending) {
334                 raise_interrupt();
335         }
336 }
337 #define INT_ON int_on()
338 static void
339 force_int_on(void)
340 {
341         suppressint = 0;
342         if (intpending)
343                 raise_interrupt();
344 }
345 #define FORCE_INT_ON force_int_on()
346 #else
347 #define INT_ON do { \
348         xbarrier(); \
349         if (--suppressint == 0 && intpending) \
350                 raise_interrupt(); \
351 } while (0)
352 #define FORCE_INT_ON do { \
353         xbarrier(); \
354         suppressint = 0; \
355         if (intpending) \
356                 raise_interrupt(); \
357 } while (0)
358 #endif /* ASH_OPTIMIZE_FOR_SIZE */
359
360 #define SAVE_INT(v) ((v) = suppressint)
361
362 #define RESTORE_INT(v) do { \
363         xbarrier(); \
364         suppressint = (v); \
365         if (suppressint == 0 && intpending) \
366                 raise_interrupt(); \
367 } while (0)
368
369 /*
370  * Ignore a signal. Avoids unnecessary system calls.
371  */
372 static void
373 ignoresig(int signo)
374 {
375         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
376                 signal(signo, SIG_IGN);
377         }
378         sigmode[signo - 1] = S_HARD_IGN;
379 }
380
381 /*
382  * Signal handler. Only one usage site - in setsignal()
383  */
384 static void
385 onsig(int signo)
386 {
387         gotsig[signo - 1] = 1;
388         pendingsig = signo;
389
390         if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
391                 if (!suppressint) {
392                         pendingsig = 0;
393                         raise_interrupt(); /* does not return */
394                 }
395                 intpending = 1;
396         }
397 }
398
399
400 /* ============ Stdout/stderr output */
401
402 static void
403 outstr(const char *p, FILE *file)
404 {
405         INT_OFF;
406         fputs(p, file);
407         INT_ON;
408 }
409
410 static void
411 flush_stdout_stderr(void)
412 {
413         INT_OFF;
414         fflush(stdout);
415         fflush(stderr);
416         INT_ON;
417 }
418
419 static void
420 flush_stderr(void)
421 {
422         INT_OFF;
423         fflush(stderr);
424         INT_ON;
425 }
426
427 static void
428 outcslow(int c, FILE *dest)
429 {
430         INT_OFF;
431         putc(c, dest);
432         fflush(dest);
433         INT_ON;
434 }
435
436 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
437 static int
438 out1fmt(const char *fmt, ...)
439 {
440         va_list ap;
441         int r;
442
443         INT_OFF;
444         va_start(ap, fmt);
445         r = vprintf(fmt, ap);
446         va_end(ap);
447         INT_ON;
448         return r;
449 }
450
451 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
452 static int
453 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
454 {
455         va_list ap;
456         int ret;
457
458         va_start(ap, fmt);
459         INT_OFF;
460         ret = vsnprintf(outbuf, length, fmt, ap);
461         va_end(ap);
462         INT_ON;
463         return ret;
464 }
465
466 static void
467 out1str(const char *p)
468 {
469         outstr(p, stdout);
470 }
471
472 static void
473 out2str(const char *p)
474 {
475         outstr(p, stderr);
476         flush_stderr();
477 }
478
479
480 /* ============ Parser structures */
481
482 /* control characters in argument strings */
483 #define CTLESC '\201'           /* escape next character */
484 #define CTLVAR '\202'           /* variable defn */
485 #define CTLENDVAR '\203'
486 #define CTLBACKQ '\204'
487 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
488 /*      CTLBACKQ | CTLQUOTE == '\205' */
489 #define CTLARI  '\206'          /* arithmetic expression */
490 #define CTLENDARI '\207'
491 #define CTLQUOTEMARK '\210'
492
493 /* variable substitution byte (follows CTLVAR) */
494 #define VSTYPE  0x0f            /* type of variable substitution */
495 #define VSNUL   0x10            /* colon--treat the empty string as unset */
496 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
497
498 /* values of VSTYPE field */
499 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
500 #define VSMINUS         0x2     /* ${var-text} */
501 #define VSPLUS          0x3     /* ${var+text} */
502 #define VSQUESTION      0x4     /* ${var?message} */
503 #define VSASSIGN        0x5     /* ${var=text} */
504 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
505 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
506 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
507 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
508 #define VSLENGTH        0xa     /* ${#var} */
509 #if ENABLE_ASH_BASH_COMPAT
510 #define VSSUBSTR        0xc     /* ${var:position:length} */
511 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
512 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
513 #endif
514
515 static const char dolatstr[] ALIGN1 = {
516         CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
517 };
518
519 #define NCMD      0
520 #define NPIPE     1
521 #define NREDIR    2
522 #define NBACKGND  3
523 #define NSUBSHELL 4
524 #define NAND      5
525 #define NOR       6
526 #define NSEMI     7
527 #define NIF       8
528 #define NWHILE    9
529 #define NUNTIL   10
530 #define NFOR     11
531 #define NCASE    12
532 #define NCLIST   13
533 #define NDEFUN   14
534 #define NARG     15
535 #define NTO      16
536 #if ENABLE_ASH_BASH_COMPAT
537 #define NTO2     17
538 #endif
539 #define NCLOBBER 18
540 #define NFROM    19
541 #define NFROMTO  20
542 #define NAPPEND  21
543 #define NTOFD    22
544 #define NFROMFD  23
545 #define NHERE    24
546 #define NXHERE   25
547 #define NNOT     26
548 #define N_NUMBER 27
549
550 union node;
551
552 struct ncmd {
553         smallint type; /* Nxxxx */
554         union node *assign;
555         union node *args;
556         union node *redirect;
557 };
558
559 struct npipe {
560         smallint type;
561         smallint pipe_backgnd;
562         struct nodelist *cmdlist;
563 };
564
565 struct nredir {
566         smallint type;
567         union node *n;
568         union node *redirect;
569 };
570
571 struct nbinary {
572         smallint type;
573         union node *ch1;
574         union node *ch2;
575 };
576
577 struct nif {
578         smallint type;
579         union node *test;
580         union node *ifpart;
581         union node *elsepart;
582 };
583
584 struct nfor {
585         smallint type;
586         union node *args;
587         union node *body;
588         char *var;
589 };
590
591 struct ncase {
592         smallint type;
593         union node *expr;
594         union node *cases;
595 };
596
597 struct nclist {
598         smallint type;
599         union node *next;
600         union node *pattern;
601         union node *body;
602 };
603
604 struct narg {
605         smallint type;
606         union node *next;
607         char *text;
608         struct nodelist *backquote;
609 };
610
611 /* nfile and ndup layout must match!
612  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
613  * that it is actually NTO2 (>&file), and change its type.
614  */
615 struct nfile {
616         smallint type;
617         union node *next;
618         int fd;
619         int _unused_dupfd;
620         union node *fname;
621         char *expfname;
622 };
623
624 struct ndup {
625         smallint type;
626         union node *next;
627         int fd;
628         int dupfd;
629         union node *vname;
630         char *_unused_expfname;
631 };
632
633 struct nhere {
634         smallint type;
635         union node *next;
636         int fd;
637         union node *doc;
638 };
639
640 struct nnot {
641         smallint type;
642         union node *com;
643 };
644
645 union node {
646         smallint type;
647         struct ncmd ncmd;
648         struct npipe npipe;
649         struct nredir nredir;
650         struct nbinary nbinary;
651         struct nif nif;
652         struct nfor nfor;
653         struct ncase ncase;
654         struct nclist nclist;
655         struct narg narg;
656         struct nfile nfile;
657         struct ndup ndup;
658         struct nhere nhere;
659         struct nnot nnot;
660 };
661
662 struct nodelist {
663         struct nodelist *next;
664         union node *n;
665 };
666
667 struct funcnode {
668         int count;
669         union node n;
670 };
671
672 /*
673  * Free a parse tree.
674  */
675 static void
676 freefunc(struct funcnode *f)
677 {
678         if (f && --f->count < 0)
679                 free(f);
680 }
681
682
683 /* ============ Debugging output */
684
685 #if DEBUG
686
687 static FILE *tracefile;
688
689 static void
690 trace_printf(const char *fmt, ...)
691 {
692         va_list va;
693
694         if (debug != 1)
695                 return;
696         va_start(va, fmt);
697         vfprintf(tracefile, fmt, va);
698         va_end(va);
699 }
700
701 static void
702 trace_vprintf(const char *fmt, va_list va)
703 {
704         if (debug != 1)
705                 return;
706         vfprintf(tracefile, fmt, va);
707 }
708
709 static void
710 trace_puts(const char *s)
711 {
712         if (debug != 1)
713                 return;
714         fputs(s, tracefile);
715 }
716
717 static void
718 trace_puts_quoted(char *s)
719 {
720         char *p;
721         char c;
722
723         if (debug != 1)
724                 return;
725         putc('"', tracefile);
726         for (p = s; *p; p++) {
727                 switch (*p) {
728                 case '\n':  c = 'n';  goto backslash;
729                 case '\t':  c = 't';  goto backslash;
730                 case '\r':  c = 'r';  goto backslash;
731                 case '"':  c = '"';  goto backslash;
732                 case '\\':  c = '\\';  goto backslash;
733                 case CTLESC:  c = 'e';  goto backslash;
734                 case CTLVAR:  c = 'v';  goto backslash;
735                 case CTLVAR+CTLQUOTE:  c = 'V'; goto backslash;
736                 case CTLBACKQ:  c = 'q';  goto backslash;
737                 case CTLBACKQ+CTLQUOTE:  c = 'Q'; goto backslash;
738  backslash:
739                         putc('\\', tracefile);
740                         putc(c, tracefile);
741                         break;
742                 default:
743                         if (*p >= ' ' && *p <= '~')
744                                 putc(*p, tracefile);
745                         else {
746                                 putc('\\', tracefile);
747                                 putc(*p >> 6 & 03, tracefile);
748                                 putc(*p >> 3 & 07, tracefile);
749                                 putc(*p & 07, tracefile);
750                         }
751                         break;
752                 }
753         }
754         putc('"', tracefile);
755 }
756
757 static void
758 trace_puts_args(char **ap)
759 {
760         if (debug != 1)
761                 return;
762         if (!*ap)
763                 return;
764         while (1) {
765                 trace_puts_quoted(*ap);
766                 if (!*++ap) {
767                         putc('\n', tracefile);
768                         break;
769                 }
770                 putc(' ', tracefile);
771         }
772 }
773
774 static void
775 opentrace(void)
776 {
777         char s[100];
778 #ifdef O_APPEND
779         int flags;
780 #endif
781
782         if (debug != 1) {
783                 if (tracefile)
784                         fflush(tracefile);
785                 /* leave open because libedit might be using it */
786                 return;
787         }
788         strcpy(s, "./trace");
789         if (tracefile) {
790                 if (!freopen(s, "a", tracefile)) {
791                         fprintf(stderr, "Can't re-open %s\n", s);
792                         debug = 0;
793                         return;
794                 }
795         } else {
796                 tracefile = fopen(s, "a");
797                 if (tracefile == NULL) {
798                         fprintf(stderr, "Can't open %s\n", s);
799                         debug = 0;
800                         return;
801                 }
802         }
803 #ifdef O_APPEND
804         flags = fcntl(fileno(tracefile), F_GETFL);
805         if (flags >= 0)
806                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
807 #endif
808         setlinebuf(tracefile);
809         fputs("\nTracing started.\n", tracefile);
810 }
811
812 static void
813 indent(int amount, char *pfx, FILE *fp)
814 {
815         int i;
816
817         for (i = 0; i < amount; i++) {
818                 if (pfx && i == amount - 1)
819                         fputs(pfx, fp);
820                 putc('\t', fp);
821         }
822 }
823
824 /* little circular references here... */
825 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
826
827 static void
828 sharg(union node *arg, FILE *fp)
829 {
830         char *p;
831         struct nodelist *bqlist;
832         int subtype;
833
834         if (arg->type != NARG) {
835                 out1fmt("<node type %d>\n", arg->type);
836                 abort();
837         }
838         bqlist = arg->narg.backquote;
839         for (p = arg->narg.text; *p; p++) {
840                 switch (*p) {
841                 case CTLESC:
842                         putc(*++p, fp);
843                         break;
844                 case CTLVAR:
845                         putc('$', fp);
846                         putc('{', fp);
847                         subtype = *++p;
848                         if (subtype == VSLENGTH)
849                                 putc('#', fp);
850
851                         while (*p != '=')
852                                 putc(*p++, fp);
853
854                         if (subtype & VSNUL)
855                                 putc(':', fp);
856
857                         switch (subtype & VSTYPE) {
858                         case VSNORMAL:
859                                 putc('}', fp);
860                                 break;
861                         case VSMINUS:
862                                 putc('-', fp);
863                                 break;
864                         case VSPLUS:
865                                 putc('+', fp);
866                                 break;
867                         case VSQUESTION:
868                                 putc('?', fp);
869                                 break;
870                         case VSASSIGN:
871                                 putc('=', fp);
872                                 break;
873                         case VSTRIMLEFT:
874                                 putc('#', fp);
875                                 break;
876                         case VSTRIMLEFTMAX:
877                                 putc('#', fp);
878                                 putc('#', fp);
879                                 break;
880                         case VSTRIMRIGHT:
881                                 putc('%', fp);
882                                 break;
883                         case VSTRIMRIGHTMAX:
884                                 putc('%', fp);
885                                 putc('%', fp);
886                                 break;
887                         case VSLENGTH:
888                                 break;
889                         default:
890                                 out1fmt("<subtype %d>", subtype);
891                         }
892                         break;
893                 case CTLENDVAR:
894                         putc('}', fp);
895                         break;
896                 case CTLBACKQ:
897                 case CTLBACKQ|CTLQUOTE:
898                         putc('$', fp);
899                         putc('(', fp);
900                         shtree(bqlist->n, -1, NULL, fp);
901                         putc(')', fp);
902                         break;
903                 default:
904                         putc(*p, fp);
905                         break;
906                 }
907         }
908 }
909
910 static void
911 shcmd(union node *cmd, FILE *fp)
912 {
913         union node *np;
914         int first;
915         const char *s;
916         int dftfd;
917
918         first = 1;
919         for (np = cmd->ncmd.args; np; np = np->narg.next) {
920                 if (!first)
921                         putc(' ', fp);
922                 sharg(np, fp);
923                 first = 0;
924         }
925         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
926                 if (!first)
927                         putc(' ', fp);
928                 dftfd = 0;
929                 switch (np->nfile.type) {
930                 case NTO:      s = ">>"+1; dftfd = 1; break;
931                 case NCLOBBER: s = ">|"; dftfd = 1; break;
932                 case NAPPEND:  s = ">>"; dftfd = 1; break;
933 #if ENABLE_ASH_BASH_COMPAT
934                 case NTO2:
935 #endif
936                 case NTOFD:    s = ">&"; dftfd = 1; break;
937                 case NFROM:    s = "<"; break;
938                 case NFROMFD:  s = "<&"; break;
939                 case NFROMTO:  s = "<>"; break;
940                 default:       s = "*error*"; break;
941                 }
942                 if (np->nfile.fd != dftfd)
943                         fprintf(fp, "%d", np->nfile.fd);
944                 fputs(s, fp);
945                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
946                         fprintf(fp, "%d", np->ndup.dupfd);
947                 } else {
948                         sharg(np->nfile.fname, fp);
949                 }
950                 first = 0;
951         }
952 }
953
954 static void
955 shtree(union node *n, int ind, char *pfx, FILE *fp)
956 {
957         struct nodelist *lp;
958         const char *s;
959
960         if (n == NULL)
961                 return;
962
963         indent(ind, pfx, fp);
964         switch (n->type) {
965         case NSEMI:
966                 s = "; ";
967                 goto binop;
968         case NAND:
969                 s = " && ";
970                 goto binop;
971         case NOR:
972                 s = " || ";
973  binop:
974                 shtree(n->nbinary.ch1, ind, NULL, fp);
975                 /* if (ind < 0) */
976                         fputs(s, fp);
977                 shtree(n->nbinary.ch2, ind, NULL, fp);
978                 break;
979         case NCMD:
980                 shcmd(n, fp);
981                 if (ind >= 0)
982                         putc('\n', fp);
983                 break;
984         case NPIPE:
985                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
986                         shcmd(lp->n, fp);
987                         if (lp->next)
988                                 fputs(" | ", fp);
989                 }
990                 if (n->npipe.pipe_backgnd)
991                         fputs(" &", fp);
992                 if (ind >= 0)
993                         putc('\n', fp);
994                 break;
995         default:
996                 fprintf(fp, "<node type %d>", n->type);
997                 if (ind >= 0)
998                         putc('\n', fp);
999                 break;
1000         }
1001 }
1002
1003 static void
1004 showtree(union node *n)
1005 {
1006         trace_puts("showtree called\n");
1007         shtree(n, 1, NULL, stdout);
1008 }
1009
1010 #define TRACE(param)    trace_printf param
1011 #define TRACEV(param)   trace_vprintf param
1012
1013 #else
1014
1015 #define TRACE(param)
1016 #define TRACEV(param)
1017
1018 #endif /* DEBUG */
1019
1020
1021 /* ============ Parser data */
1022
1023 /*
1024  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1025  */
1026 struct strlist {
1027         struct strlist *next;
1028         char *text;
1029 };
1030
1031 struct alias;
1032
1033 struct strpush {
1034         struct strpush *prev;   /* preceding string on stack */
1035         char *prev_string;
1036         int prev_left_in_line;
1037 #if ENABLE_ASH_ALIAS
1038         struct alias *ap;       /* if push was associated with an alias */
1039 #endif
1040         char *string;           /* remember the string since it may change */
1041 };
1042
1043 struct parsefile {
1044         struct parsefile *prev; /* preceding file on stack */
1045         int linno;              /* current line */
1046         int fd;                 /* file descriptor (or -1 if string) */
1047         int left_in_line;       /* number of chars left in this line */
1048         int left_in_buffer;     /* number of chars left in this buffer past the line */
1049         char *next_to_pgetc;    /* next char in buffer */
1050         char *buf;              /* input buffer */
1051         struct strpush *strpush; /* for pushing strings at this level */
1052         struct strpush basestrpush; /* so pushing one is fast */
1053 };
1054
1055 static struct parsefile basepf;        /* top level input file */
1056 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1057 static int startlinno;                 /* line # where last token started */
1058 static char *commandname;              /* currently executing command */
1059 static struct strlist *cmdenviron;     /* environment for builtin command */
1060 static uint8_t exitstatus;             /* exit status of last command */
1061
1062
1063 /* ============ Message printing */
1064
1065 static void
1066 ash_vmsg(const char *msg, va_list ap)
1067 {
1068         fprintf(stderr, "%s: ", arg0);
1069         if (commandname) {
1070                 if (strcmp(arg0, commandname))
1071                         fprintf(stderr, "%s: ", commandname);
1072                 if (!iflag || g_parsefile->fd)
1073                         fprintf(stderr, "line %d: ", startlinno);
1074         }
1075         vfprintf(stderr, msg, ap);
1076         outcslow('\n', stderr);
1077 }
1078
1079 /*
1080  * Exverror is called to raise the error exception.  If the second argument
1081  * is not NULL then error prints an error message using printf style
1082  * formatting.  It then raises the error exception.
1083  */
1084 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1085 static void
1086 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1087 {
1088 #if DEBUG
1089         if (msg) {
1090                 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1091                 TRACEV((msg, ap));
1092                 TRACE(("\") pid=%d\n", getpid()));
1093         } else
1094                 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1095         if (msg)
1096 #endif
1097                 ash_vmsg(msg, ap);
1098
1099         flush_stdout_stderr();
1100         raise_exception(cond);
1101         /* NOTREACHED */
1102 }
1103
1104 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1105 static void
1106 ash_msg_and_raise_error(const char *msg, ...)
1107 {
1108         va_list ap;
1109
1110         va_start(ap, msg);
1111         ash_vmsg_and_raise(EXERROR, msg, ap);
1112         /* NOTREACHED */
1113         va_end(ap);
1114 }
1115
1116 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1117 static void
1118 ash_msg_and_raise(int cond, const char *msg, ...)
1119 {
1120         va_list ap;
1121
1122         va_start(ap, msg);
1123         ash_vmsg_and_raise(cond, msg, ap);
1124         /* NOTREACHED */
1125         va_end(ap);
1126 }
1127
1128 /*
1129  * error/warning routines for external builtins
1130  */
1131 static void
1132 ash_msg(const char *fmt, ...)
1133 {
1134         va_list ap;
1135
1136         va_start(ap, fmt);
1137         ash_vmsg(fmt, ap);
1138         va_end(ap);
1139 }
1140
1141 /*
1142  * Return a string describing an error.  The returned string may be a
1143  * pointer to a static buffer that will be overwritten on the next call.
1144  * Action describes the operation that got the error.
1145  */
1146 static const char *
1147 errmsg(int e, const char *em)
1148 {
1149         if (e == ENOENT || e == ENOTDIR) {
1150                 return em;
1151         }
1152         return strerror(e);
1153 }
1154
1155
1156 /* ============ Memory allocation */
1157
1158 /*
1159  * It appears that grabstackstr() will barf with such alignments
1160  * because stalloc() will return a string allocated in a new stackblock.
1161  */
1162 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1163 enum {
1164         /* Most machines require the value returned from malloc to be aligned
1165          * in some way.  The following macro will get this right
1166          * on many machines.  */
1167         SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1168         /* Minimum size of a block */
1169         MINSIZE = SHELL_ALIGN(504),
1170 };
1171
1172 struct stack_block {
1173         struct stack_block *prev;
1174         char space[MINSIZE];
1175 };
1176
1177 struct stackmark {
1178         struct stack_block *stackp;
1179         char *stacknxt;
1180         size_t stacknleft;
1181         struct stackmark *marknext;
1182 };
1183
1184
1185 struct globals_memstack {
1186         struct stack_block *g_stackp; // = &stackbase;
1187         struct stackmark *markp;
1188         char *g_stacknxt; // = stackbase.space;
1189         char *sstrend; // = stackbase.space + MINSIZE;
1190         size_t g_stacknleft; // = MINSIZE;
1191         int    herefd; // = -1;
1192         struct stack_block stackbase;
1193 };
1194 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1195 #define G_memstack (*ash_ptr_to_globals_memstack)
1196 #define g_stackp     (G_memstack.g_stackp    )
1197 #define markp        (G_memstack.markp       )
1198 #define g_stacknxt   (G_memstack.g_stacknxt  )
1199 #define sstrend      (G_memstack.sstrend     )
1200 #define g_stacknleft (G_memstack.g_stacknleft)
1201 #define herefd       (G_memstack.herefd      )
1202 #define stackbase    (G_memstack.stackbase   )
1203 #define INIT_G_memstack() do { \
1204         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1205         barrier(); \
1206         g_stackp = &stackbase; \
1207         g_stacknxt = stackbase.space; \
1208         g_stacknleft = MINSIZE; \
1209         sstrend = stackbase.space + MINSIZE; \
1210         herefd = -1; \
1211 } while (0)
1212
1213 #define stackblock()     ((void *)g_stacknxt)
1214 #define stackblocksize() g_stacknleft
1215
1216
1217 static void *
1218 ckrealloc(void * p, size_t nbytes)
1219 {
1220         p = realloc(p, nbytes);
1221         if (!p)
1222                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1223         return p;
1224 }
1225
1226 static void *
1227 ckmalloc(size_t nbytes)
1228 {
1229         return ckrealloc(NULL, nbytes);
1230 }
1231
1232 static void *
1233 ckzalloc(size_t nbytes)
1234 {
1235         return memset(ckmalloc(nbytes), 0, nbytes);
1236 }
1237
1238 /*
1239  * Make a copy of a string in safe storage.
1240  */
1241 static char *
1242 ckstrdup(const char *s)
1243 {
1244         char *p = strdup(s);
1245         if (!p)
1246                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1247         return p;
1248 }
1249
1250 /*
1251  * Parse trees for commands are allocated in lifo order, so we use a stack
1252  * to make this more efficient, and also to avoid all sorts of exception
1253  * handling code to handle interrupts in the middle of a parse.
1254  *
1255  * The size 504 was chosen because the Ultrix malloc handles that size
1256  * well.
1257  */
1258 static void *
1259 stalloc(size_t nbytes)
1260 {
1261         char *p;
1262         size_t aligned;
1263
1264         aligned = SHELL_ALIGN(nbytes);
1265         if (aligned > g_stacknleft) {
1266                 size_t len;
1267                 size_t blocksize;
1268                 struct stack_block *sp;
1269
1270                 blocksize = aligned;
1271                 if (blocksize < MINSIZE)
1272                         blocksize = MINSIZE;
1273                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1274                 if (len < blocksize)
1275                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1276                 INT_OFF;
1277                 sp = ckmalloc(len);
1278                 sp->prev = g_stackp;
1279                 g_stacknxt = sp->space;
1280                 g_stacknleft = blocksize;
1281                 sstrend = g_stacknxt + blocksize;
1282                 g_stackp = sp;
1283                 INT_ON;
1284         }
1285         p = g_stacknxt;
1286         g_stacknxt += aligned;
1287         g_stacknleft -= aligned;
1288         return p;
1289 }
1290
1291 static void *
1292 stzalloc(size_t nbytes)
1293 {
1294         return memset(stalloc(nbytes), 0, nbytes);
1295 }
1296
1297 static void
1298 stunalloc(void *p)
1299 {
1300 #if DEBUG
1301         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1302                 write(STDERR_FILENO, "stunalloc\n", 10);
1303                 abort();
1304         }
1305 #endif
1306         g_stacknleft += g_stacknxt - (char *)p;
1307         g_stacknxt = p;
1308 }
1309
1310 /*
1311  * Like strdup but works with the ash stack.
1312  */
1313 static char *
1314 ststrdup(const char *p)
1315 {
1316         size_t len = strlen(p) + 1;
1317         return memcpy(stalloc(len), p, len);
1318 }
1319
1320 static void
1321 setstackmark(struct stackmark *mark)
1322 {
1323         mark->stackp = g_stackp;
1324         mark->stacknxt = g_stacknxt;
1325         mark->stacknleft = g_stacknleft;
1326         mark->marknext = markp;
1327         markp = mark;
1328 }
1329
1330 static void
1331 popstackmark(struct stackmark *mark)
1332 {
1333         struct stack_block *sp;
1334
1335         if (!mark->stackp)
1336                 return;
1337
1338         INT_OFF;
1339         markp = mark->marknext;
1340         while (g_stackp != mark->stackp) {
1341                 sp = g_stackp;
1342                 g_stackp = sp->prev;
1343                 free(sp);
1344         }
1345         g_stacknxt = mark->stacknxt;
1346         g_stacknleft = mark->stacknleft;
1347         sstrend = mark->stacknxt + mark->stacknleft;
1348         INT_ON;
1349 }
1350
1351 /*
1352  * When the parser reads in a string, it wants to stick the string on the
1353  * stack and only adjust the stack pointer when it knows how big the
1354  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1355  * of space on top of the stack and stackblocklen returns the length of
1356  * this block.  Growstackblock will grow this space by at least one byte,
1357  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1358  * part of the block that has been used.
1359  */
1360 static void
1361 growstackblock(void)
1362 {
1363         size_t newlen;
1364
1365         newlen = g_stacknleft * 2;
1366         if (newlen < g_stacknleft)
1367                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1368         if (newlen < 128)
1369                 newlen += 128;
1370
1371         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1372                 struct stack_block *oldstackp;
1373                 struct stackmark *xmark;
1374                 struct stack_block *sp;
1375                 struct stack_block *prevstackp;
1376                 size_t grosslen;
1377
1378                 INT_OFF;
1379                 oldstackp = g_stackp;
1380                 sp = g_stackp;
1381                 prevstackp = sp->prev;
1382                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1383                 sp = ckrealloc(sp, grosslen);
1384                 sp->prev = prevstackp;
1385                 g_stackp = sp;
1386                 g_stacknxt = sp->space;
1387                 g_stacknleft = newlen;
1388                 sstrend = sp->space + newlen;
1389
1390                 /*
1391                  * Stack marks pointing to the start of the old block
1392                  * must be relocated to point to the new block
1393                  */
1394                 xmark = markp;
1395                 while (xmark != NULL && xmark->stackp == oldstackp) {
1396                         xmark->stackp = g_stackp;
1397                         xmark->stacknxt = g_stacknxt;
1398                         xmark->stacknleft = g_stacknleft;
1399                         xmark = xmark->marknext;
1400                 }
1401                 INT_ON;
1402         } else {
1403                 char *oldspace = g_stacknxt;
1404                 size_t oldlen = g_stacknleft;
1405                 char *p = stalloc(newlen);
1406
1407                 /* free the space we just allocated */
1408                 g_stacknxt = memcpy(p, oldspace, oldlen);
1409                 g_stacknleft += newlen;
1410         }
1411 }
1412
1413 static void
1414 grabstackblock(size_t len)
1415 {
1416         len = SHELL_ALIGN(len);
1417         g_stacknxt += len;
1418         g_stacknleft -= len;
1419 }
1420
1421 /*
1422  * The following routines are somewhat easier to use than the above.
1423  * The user declares a variable of type STACKSTR, which may be declared
1424  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1425  * the user uses the macro STPUTC to add characters to the string.  In
1426  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1427  * grown as necessary.  When the user is done, she can just leave the
1428  * string there and refer to it using stackblock().  Or she can allocate
1429  * the space for it using grabstackstr().  If it is necessary to allow
1430  * someone else to use the stack temporarily and then continue to grow
1431  * the string, the user should use grabstack to allocate the space, and
1432  * then call ungrabstr(p) to return to the previous mode of operation.
1433  *
1434  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1435  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1436  * is space for at least one character.
1437  */
1438 static void *
1439 growstackstr(void)
1440 {
1441         size_t len = stackblocksize();
1442         if (herefd >= 0 && len >= 1024) {
1443                 full_write(herefd, stackblock(), len);
1444                 return stackblock();
1445         }
1446         growstackblock();
1447         return (char *)stackblock() + len;
1448 }
1449
1450 /*
1451  * Called from CHECKSTRSPACE.
1452  */
1453 static char *
1454 makestrspace(size_t newlen, char *p)
1455 {
1456         size_t len = p - g_stacknxt;
1457         size_t size = stackblocksize();
1458
1459         for (;;) {
1460                 size_t nleft;
1461
1462                 size = stackblocksize();
1463                 nleft = size - len;
1464                 if (nleft >= newlen)
1465                         break;
1466                 growstackblock();
1467         }
1468         return (char *)stackblock() + len;
1469 }
1470
1471 static char *
1472 stack_nputstr(const char *s, size_t n, char *p)
1473 {
1474         p = makestrspace(n, p);
1475         p = (char *)memcpy(p, s, n) + n;
1476         return p;
1477 }
1478
1479 static char *
1480 stack_putstr(const char *s, char *p)
1481 {
1482         return stack_nputstr(s, strlen(s), p);
1483 }
1484
1485 static char *
1486 _STPUTC(int c, char *p)
1487 {
1488         if (p == sstrend)
1489                 p = growstackstr();
1490         *p++ = c;
1491         return p;
1492 }
1493
1494 #define STARTSTACKSTR(p)        ((p) = stackblock())
1495 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1496 #define CHECKSTRSPACE(n, p) do { \
1497         char *q = (p); \
1498         size_t l = (n); \
1499         size_t m = sstrend - q; \
1500         if (l > m) \
1501                 (p) = makestrspace(l, q); \
1502 } while (0)
1503 #define USTPUTC(c, p)           (*(p)++ = (c))
1504 #define STACKSTRNUL(p) do { \
1505         if ((p) == sstrend) \
1506                 (p) = growstackstr(); \
1507         *(p) = '\0'; \
1508 } while (0)
1509 #define STUNPUTC(p)             (--(p))
1510 #define STTOPC(p)               ((p)[-1])
1511 #define STADJUST(amount, p)     ((p) += (amount))
1512
1513 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1514 #define ungrabstackstr(s, p)    stunalloc(s)
1515 #define stackstrend()           ((void *)sstrend)
1516
1517
1518 /* ============ String helpers */
1519
1520 /*
1521  * prefix -- see if pfx is a prefix of string.
1522  */
1523 static char *
1524 prefix(const char *string, const char *pfx)
1525 {
1526         while (*pfx) {
1527                 if (*pfx++ != *string++)
1528                         return NULL;
1529         }
1530         return (char *) string;
1531 }
1532
1533 /*
1534  * Check for a valid number.  This should be elsewhere.
1535  */
1536 static int
1537 is_number(const char *p)
1538 {
1539         do {
1540                 if (!isdigit(*p))
1541                         return 0;
1542         } while (*++p != '\0');
1543         return 1;
1544 }
1545
1546 /*
1547  * Convert a string of digits to an integer, printing an error message on
1548  * failure.
1549  */
1550 static int
1551 number(const char *s)
1552 {
1553         if (!is_number(s))
1554                 ash_msg_and_raise_error(illnum, s);
1555         return atoi(s);
1556 }
1557
1558 /*
1559  * Produce a possibly single quoted string suitable as input to the shell.
1560  * The return string is allocated on the stack.
1561  */
1562 static char *
1563 single_quote(const char *s)
1564 {
1565         char *p;
1566
1567         STARTSTACKSTR(p);
1568
1569         do {
1570                 char *q;
1571                 size_t len;
1572
1573                 len = strchrnul(s, '\'') - s;
1574
1575                 q = p = makestrspace(len + 3, p);
1576
1577                 *q++ = '\'';
1578                 q = (char *)memcpy(q, s, len) + len;
1579                 *q++ = '\'';
1580                 s += len;
1581
1582                 STADJUST(q - p, p);
1583
1584                 len = strspn(s, "'");
1585                 if (!len)
1586                         break;
1587
1588                 q = p = makestrspace(len + 3, p);
1589
1590                 *q++ = '"';
1591                 q = (char *)memcpy(q, s, len) + len;
1592                 *q++ = '"';
1593                 s += len;
1594
1595                 STADJUST(q - p, p);
1596         } while (*s);
1597
1598         USTPUTC(0, p);
1599
1600         return stackblock();
1601 }
1602
1603
1604 /* ============ nextopt */
1605
1606 static char **argptr;                  /* argument list for builtin commands */
1607 static char *optionarg;                /* set by nextopt (like getopt) */
1608 static char *optptr;                   /* used by nextopt */
1609
1610 /*
1611  * XXX - should get rid of. Have all builtins use getopt(3).
1612  * The library getopt must have the BSD extension static variable
1613  * "optreset", otherwise it can't be used within the shell safely.
1614  *
1615  * Standard option processing (a la getopt) for builtin routines.
1616  * The only argument that is passed to nextopt is the option string;
1617  * the other arguments are unnecessary. It returns the character,
1618  * or '\0' on end of input.
1619  */
1620 static int
1621 nextopt(const char *optstring)
1622 {
1623         char *p;
1624         const char *q;
1625         char c;
1626
1627         p = optptr;
1628         if (p == NULL || *p == '\0') {
1629                 /* We ate entire "-param", take next one */
1630                 p = *argptr;
1631                 if (p == NULL)
1632                         return '\0';
1633                 if (*p != '-')
1634                         return '\0';
1635                 if (*++p == '\0') /* just "-" ? */
1636                         return '\0';
1637                 argptr++;
1638                 if (LONE_DASH(p)) /* "--" ? */
1639                         return '\0';
1640                 /* p => next "-param" */
1641         }
1642         /* p => some option char in the middle of a "-param" */
1643         c = *p++;
1644         for (q = optstring; *q != c;) {
1645                 if (*q == '\0')
1646                         ash_msg_and_raise_error("illegal option -%c", c);
1647                 if (*++q == ':')
1648                         q++;
1649         }
1650         if (*++q == ':') {
1651                 if (*p == '\0') {
1652                         p = *argptr++;
1653                         if (p == NULL)
1654                                 ash_msg_and_raise_error("no arg for -%c option", c);
1655                 }
1656                 optionarg = p;
1657                 p = NULL;
1658         }
1659         optptr = p;
1660         return c;
1661 }
1662
1663
1664 /* ============ Shell variables */
1665
1666 /*
1667  * The parsefile structure pointed to by the global variable parsefile
1668  * contains information about the current file being read.
1669  */
1670 struct shparam {
1671         int nparam;             /* # of positional parameters (without $0) */
1672 #if ENABLE_ASH_GETOPTS
1673         int optind;             /* next parameter to be processed by getopts */
1674         int optoff;             /* used by getopts */
1675 #endif
1676         unsigned char malloced; /* if parameter list dynamically allocated */
1677         char **p;               /* parameter list */
1678 };
1679
1680 /*
1681  * Free the list of positional parameters.
1682  */
1683 static void
1684 freeparam(volatile struct shparam *param)
1685 {
1686         if (param->malloced) {
1687                 char **ap, **ap1;
1688                 ap = ap1 = param->p;
1689                 while (*ap)
1690                         free(*ap++);
1691                 free(ap1);
1692         }
1693 }
1694
1695 #if ENABLE_ASH_GETOPTS
1696 static void getoptsreset(const char *value);
1697 #endif
1698
1699 struct var {
1700         struct var *next;               /* next entry in hash list */
1701         int flags;                      /* flags are defined above */
1702         const char *text;               /* name=value */
1703         void (*func)(const char *);     /* function to be called when  */
1704                                         /* the variable gets set/unset */
1705 };
1706
1707 struct localvar {
1708         struct localvar *next;          /* next local variable in list */
1709         struct var *vp;                 /* the variable that was made local */
1710         int flags;                      /* saved flags */
1711         const char *text;               /* saved text */
1712 };
1713
1714 /* flags */
1715 #define VEXPORT         0x01    /* variable is exported */
1716 #define VREADONLY       0x02    /* variable cannot be modified */
1717 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1718 #define VTEXTFIXED      0x08    /* text is statically allocated */
1719 #define VSTACK          0x10    /* text is allocated on the stack */
1720 #define VUNSET          0x20    /* the variable is not set */
1721 #define VNOFUNC         0x40    /* don't call the callback function */
1722 #define VNOSET          0x80    /* do not set variable - just readonly test */
1723 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1724 #if ENABLE_ASH_RANDOM_SUPPORT
1725 # define VDYNAMIC       0x200   /* dynamic variable */
1726 #else
1727 # define VDYNAMIC       0
1728 #endif
1729
1730 #ifdef IFS_BROKEN
1731 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1732 #define defifs (defifsvar + 4)
1733 #else
1734 static const char defifs[] ALIGN1 = " \t\n";
1735 #endif
1736
1737
1738 /* Need to be before varinit_data[] */
1739 #if ENABLE_LOCALE_SUPPORT
1740 static void
1741 change_lc_all(const char *value)
1742 {
1743         if (value && *value != '\0')
1744                 setlocale(LC_ALL, value);
1745 }
1746 static void
1747 change_lc_ctype(const char *value)
1748 {
1749         if (value && *value != '\0')
1750                 setlocale(LC_CTYPE, value);
1751 }
1752 #endif
1753 #if ENABLE_ASH_MAIL
1754 static void chkmail(void);
1755 static void changemail(const char *);
1756 #endif
1757 static void changepath(const char *);
1758 #if ENABLE_ASH_RANDOM_SUPPORT
1759 static void change_random(const char *);
1760 #endif
1761
1762 static const struct {
1763         int flags;
1764         const char *text;
1765         void (*func)(const char *);
1766 } varinit_data[] = {
1767 #ifdef IFS_BROKEN
1768         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1769 #else
1770         { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0"     , NULL            },
1771 #endif
1772 #if ENABLE_ASH_MAIL
1773         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0"    , changemail      },
1774         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail      },
1775 #endif
1776         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1777         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1778         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1779         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1780 #if ENABLE_ASH_GETOPTS
1781         { VSTRFIXED|VTEXTFIXED       , "OPTIND=1"  , getoptsreset    },
1782 #endif
1783 #if ENABLE_ASH_RANDOM_SUPPORT
1784         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1785 #endif
1786 #if ENABLE_LOCALE_SUPPORT
1787         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0"  , change_lc_all   },
1788         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1789 #endif
1790 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1791         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL            },
1792 #endif
1793 };
1794
1795 struct redirtab;
1796
1797 struct globals_var {
1798         struct shparam shellparam;      /* $@ current positional parameters */
1799         struct redirtab *redirlist;
1800         int g_nullredirs;
1801         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1802         struct var *vartab[VTABSIZE];
1803         struct var varinit[ARRAY_SIZE(varinit_data)];
1804 };
1805 extern struct globals_var *const ash_ptr_to_globals_var;
1806 #define G_var (*ash_ptr_to_globals_var)
1807 #define shellparam    (G_var.shellparam   )
1808 //#define redirlist     (G_var.redirlist    )
1809 #define g_nullredirs  (G_var.g_nullredirs )
1810 #define preverrout_fd (G_var.preverrout_fd)
1811 #define vartab        (G_var.vartab       )
1812 #define varinit       (G_var.varinit      )
1813 #define INIT_G_var() do { \
1814         unsigned i; \
1815         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1816         barrier(); \
1817         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1818                 varinit[i].flags = varinit_data[i].flags; \
1819                 varinit[i].text  = varinit_data[i].text; \
1820                 varinit[i].func  = varinit_data[i].func; \
1821         } \
1822 } while (0)
1823
1824 #define vifs      varinit[0]
1825 #if ENABLE_ASH_MAIL
1826 # define vmail    (&vifs)[1]
1827 # define vmpath   (&vmail)[1]
1828 # define vpath    (&vmpath)[1]
1829 #else
1830 # define vpath    (&vifs)[1]
1831 #endif
1832 #define vps1      (&vpath)[1]
1833 #define vps2      (&vps1)[1]
1834 #define vps4      (&vps2)[1]
1835 #if ENABLE_ASH_GETOPTS
1836 # define voptind  (&vps4)[1]
1837 # if ENABLE_ASH_RANDOM_SUPPORT
1838 #  define vrandom (&voptind)[1]
1839 # endif
1840 #else
1841 # if ENABLE_ASH_RANDOM_SUPPORT
1842 #  define vrandom (&vps4)[1]
1843 # endif
1844 #endif
1845
1846 /*
1847  * The following macros access the values of the above variables.
1848  * They have to skip over the name.  They return the null string
1849  * for unset variables.
1850  */
1851 #define ifsval()        (vifs.text + 4)
1852 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1853 #if ENABLE_ASH_MAIL
1854 # define mailval()      (vmail.text + 5)
1855 # define mpathval()     (vmpath.text + 9)
1856 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
1857 #endif
1858 #define pathval()       (vpath.text + 5)
1859 #define ps1val()        (vps1.text + 4)
1860 #define ps2val()        (vps2.text + 4)
1861 #define ps4val()        (vps4.text + 4)
1862 #if ENABLE_ASH_GETOPTS
1863 # define optindval()    (voptind.text + 7)
1864 #endif
1865
1866
1867 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
1868 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
1869
1870 #if ENABLE_ASH_GETOPTS
1871 static void
1872 getoptsreset(const char *value)
1873 {
1874         shellparam.optind = number(value);
1875         shellparam.optoff = -1;
1876 }
1877 #endif
1878
1879 /*
1880  * Return of a legal variable name (a letter or underscore followed by zero or
1881  * more letters, underscores, and digits).
1882  */
1883 static char *
1884 endofname(const char *name)
1885 {
1886         char *p;
1887
1888         p = (char *) name;
1889         if (!is_name(*p))
1890                 return p;
1891         while (*++p) {
1892                 if (!is_in_name(*p))
1893                         break;
1894         }
1895         return p;
1896 }
1897
1898 /*
1899  * Compares two strings up to the first = or '\0'.  The first
1900  * string must be terminated by '='; the second may be terminated by
1901  * either '=' or '\0'.
1902  */
1903 static int
1904 varcmp(const char *p, const char *q)
1905 {
1906         int c, d;
1907
1908         while ((c = *p) == (d = *q)) {
1909                 if (!c || c == '=')
1910                         goto out;
1911                 p++;
1912                 q++;
1913         }
1914         if (c == '=')
1915                 c = '\0';
1916         if (d == '=')
1917                 d = '\0';
1918  out:
1919         return c - d;
1920 }
1921
1922 static int
1923 varequal(const char *a, const char *b)
1924 {
1925         return !varcmp(a, b);
1926 }
1927
1928 /*
1929  * Find the appropriate entry in the hash table from the name.
1930  */
1931 static struct var **
1932 hashvar(const char *p)
1933 {
1934         unsigned hashval;
1935
1936         hashval = ((unsigned char) *p) << 4;
1937         while (*p && *p != '=')
1938                 hashval += (unsigned char) *p++;
1939         return &vartab[hashval % VTABSIZE];
1940 }
1941
1942 static int
1943 vpcmp(const void *a, const void *b)
1944 {
1945         return varcmp(*(const char **)a, *(const char **)b);
1946 }
1947
1948 /*
1949  * This routine initializes the builtin variables.
1950  */
1951 static void
1952 initvar(void)
1953 {
1954         struct var *vp;
1955         struct var *end;
1956         struct var **vpp;
1957
1958         /*
1959          * PS1 depends on uid
1960          */
1961 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1962         vps1.text = "PS1=\\w \\$ ";
1963 #else
1964         if (!geteuid())
1965                 vps1.text = "PS1=# ";
1966 #endif
1967         vp = varinit;
1968         end = vp + ARRAY_SIZE(varinit);
1969         do {
1970                 vpp = hashvar(vp->text);
1971                 vp->next = *vpp;
1972                 *vpp = vp;
1973         } while (++vp < end);
1974 }
1975
1976 static struct var **
1977 findvar(struct var **vpp, const char *name)
1978 {
1979         for (; *vpp; vpp = &(*vpp)->next) {
1980                 if (varequal((*vpp)->text, name)) {
1981                         break;
1982                 }
1983         }
1984         return vpp;
1985 }
1986
1987 /*
1988  * Find the value of a variable.  Returns NULL if not set.
1989  */
1990 static char *
1991 lookupvar(const char *name)
1992 {
1993         struct var *v;
1994
1995         v = *findvar(hashvar(name), name);
1996         if (v) {
1997 #if ENABLE_ASH_RANDOM_SUPPORT
1998         /*
1999          * Dynamic variables are implemented roughly the same way they are
2000          * in bash. Namely, they're "special" so long as they aren't unset.
2001          * As soon as they're unset, they're no longer dynamic, and dynamic
2002          * lookup will no longer happen at that point. -- PFM.
2003          */
2004                 if ((v->flags & VDYNAMIC))
2005                         (*v->func)(NULL);
2006 #endif
2007                 if (!(v->flags & VUNSET))
2008                         return strchrnul(v->text, '=') + 1;
2009         }
2010         return NULL;
2011 }
2012
2013 /*
2014  * Search the environment of a builtin command.
2015  */
2016 static char *
2017 bltinlookup(const char *name)
2018 {
2019         struct strlist *sp;
2020
2021         for (sp = cmdenviron; sp; sp = sp->next) {
2022                 if (varequal(sp->text, name))
2023                         return strchrnul(sp->text, '=') + 1;
2024         }
2025         return lookupvar(name);
2026 }
2027
2028 /*
2029  * Same as setvar except that the variable and value are passed in
2030  * the first argument as name=value.  Since the first argument will
2031  * be actually stored in the table, it should not be a string that
2032  * will go away.
2033  * Called with interrupts off.
2034  */
2035 static void
2036 setvareq(char *s, int flags)
2037 {
2038         struct var *vp, **vpp;
2039
2040         vpp = hashvar(s);
2041         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2042         vp = *findvar(vpp, s);
2043         if (vp) {
2044                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2045                         const char *n;
2046
2047                         if (flags & VNOSAVE)
2048                                 free(s);
2049                         n = vp->text;
2050                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2051                 }
2052
2053                 if (flags & VNOSET)
2054                         return;
2055
2056                 if (vp->func && (flags & VNOFUNC) == 0)
2057                         (*vp->func)(strchrnul(s, '=') + 1);
2058
2059                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2060                         free((char*)vp->text);
2061
2062                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2063         } else {
2064                 if (flags & VNOSET)
2065                         return;
2066                 /* not found */
2067                 vp = ckzalloc(sizeof(*vp));
2068                 vp->next = *vpp;
2069                 /*vp->func = NULL; - ckzalloc did it */
2070                 *vpp = vp;
2071         }
2072         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2073                 s = ckstrdup(s);
2074         vp->text = s;
2075         vp->flags = flags;
2076 }
2077
2078 /*
2079  * Set the value of a variable.  The flags argument is ored with the
2080  * flags of the variable.  If val is NULL, the variable is unset.
2081  */
2082 static void
2083 setvar(const char *name, const char *val, int flags)
2084 {
2085         char *p, *q;
2086         size_t namelen;
2087         char *nameeq;
2088         size_t vallen;
2089
2090         q = endofname(name);
2091         p = strchrnul(q, '=');
2092         namelen = p - name;
2093         if (!namelen || p != q)
2094                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2095         vallen = 0;
2096         if (val == NULL) {
2097                 flags |= VUNSET;
2098         } else {
2099                 vallen = strlen(val);
2100         }
2101         INT_OFF;
2102         nameeq = ckmalloc(namelen + vallen + 2);
2103         p = (char *)memcpy(nameeq, name, namelen) + namelen;
2104         if (val) {
2105                 *p++ = '=';
2106                 p = (char *)memcpy(p, val, vallen) + vallen;
2107         }
2108         *p = '\0';
2109         setvareq(nameeq, flags | VNOSAVE);
2110         INT_ON;
2111 }
2112
2113 #if ENABLE_ASH_GETOPTS
2114 /*
2115  * Safe version of setvar, returns 1 on success 0 on failure.
2116  */
2117 static int
2118 setvarsafe(const char *name, const char *val, int flags)
2119 {
2120         int err;
2121         volatile int saveint;
2122         struct jmploc *volatile savehandler = exception_handler;
2123         struct jmploc jmploc;
2124
2125         SAVE_INT(saveint);
2126         if (setjmp(jmploc.loc))
2127                 err = 1;
2128         else {
2129                 exception_handler = &jmploc;
2130                 setvar(name, val, flags);
2131                 err = 0;
2132         }
2133         exception_handler = savehandler;
2134         RESTORE_INT(saveint);
2135         return err;
2136 }
2137 #endif
2138
2139 /*
2140  * Unset the specified variable.
2141  */
2142 static int
2143 unsetvar(const char *s)
2144 {
2145         struct var **vpp;
2146         struct var *vp;
2147         int retval;
2148
2149         vpp = findvar(hashvar(s), s);
2150         vp = *vpp;
2151         retval = 2;
2152         if (vp) {
2153                 int flags = vp->flags;
2154
2155                 retval = 1;
2156                 if (flags & VREADONLY)
2157                         goto out;
2158 #if ENABLE_ASH_RANDOM_SUPPORT
2159                 vp->flags &= ~VDYNAMIC;
2160 #endif
2161                 if (flags & VUNSET)
2162                         goto ok;
2163                 if ((flags & VSTRFIXED) == 0) {
2164                         INT_OFF;
2165                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2166                                 free((char*)vp->text);
2167                         *vpp = vp->next;
2168                         free(vp);
2169                         INT_ON;
2170                 } else {
2171                         setvar(s, 0, 0);
2172                         vp->flags &= ~VEXPORT;
2173                 }
2174  ok:
2175                 retval = 0;
2176         }
2177  out:
2178         return retval;
2179 }
2180
2181 /*
2182  * Process a linked list of variable assignments.
2183  */
2184 static void
2185 listsetvar(struct strlist *list_set_var, int flags)
2186 {
2187         struct strlist *lp = list_set_var;
2188
2189         if (!lp)
2190                 return;
2191         INT_OFF;
2192         do {
2193                 setvareq(lp->text, flags);
2194                 lp = lp->next;
2195         } while (lp);
2196         INT_ON;
2197 }
2198
2199 /*
2200  * Generate a list of variables satisfying the given conditions.
2201  */
2202 static char **
2203 listvars(int on, int off, char ***end)
2204 {
2205         struct var **vpp;
2206         struct var *vp;
2207         char **ep;
2208         int mask;
2209
2210         STARTSTACKSTR(ep);
2211         vpp = vartab;
2212         mask = on | off;
2213         do {
2214                 for (vp = *vpp; vp; vp = vp->next) {
2215                         if ((vp->flags & mask) == on) {
2216                                 if (ep == stackstrend())
2217                                         ep = growstackstr();
2218                                 *ep++ = (char *) vp->text;
2219                         }
2220                 }
2221         } while (++vpp < vartab + VTABSIZE);
2222         if (ep == stackstrend())
2223                 ep = growstackstr();
2224         if (end)
2225                 *end = ep;
2226         *ep++ = NULL;
2227         return grabstackstr(ep);
2228 }
2229
2230
2231 /* ============ Path search helper
2232  *
2233  * The variable path (passed by reference) should be set to the start
2234  * of the path before the first call; padvance will update
2235  * this value as it proceeds.  Successive calls to padvance will return
2236  * the possible path expansions in sequence.  If an option (indicated by
2237  * a percent sign) appears in the path entry then the global variable
2238  * pathopt will be set to point to it; otherwise pathopt will be set to
2239  * NULL.
2240  */
2241 static const char *pathopt;     /* set by padvance */
2242
2243 static char *
2244 padvance(const char **path, const char *name)
2245 {
2246         const char *p;
2247         char *q;
2248         const char *start;
2249         size_t len;
2250
2251         if (*path == NULL)
2252                 return NULL;
2253         start = *path;
2254         for (p = start; *p && *p != ':' && *p != '%'; p++)
2255                 continue;
2256         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2257         while (stackblocksize() < len)
2258                 growstackblock();
2259         q = stackblock();
2260         if (p != start) {
2261                 memcpy(q, start, p - start);
2262                 q += p - start;
2263                 *q++ = '/';
2264         }
2265         strcpy(q, name);
2266         pathopt = NULL;
2267         if (*p == '%') {
2268                 pathopt = ++p;
2269                 while (*p && *p != ':')
2270                         p++;
2271         }
2272         if (*p == ':')
2273                 *path = p + 1;
2274         else
2275                 *path = NULL;
2276         return stalloc(len);
2277 }
2278
2279
2280 /* ============ Prompt */
2281
2282 static smallint doprompt;                   /* if set, prompt the user */
2283 static smallint needprompt;                 /* true if interactive and at start of line */
2284
2285 #if ENABLE_FEATURE_EDITING
2286 static line_input_t *line_input_state;
2287 static const char *cmdedit_prompt;
2288 static void
2289 putprompt(const char *s)
2290 {
2291         if (ENABLE_ASH_EXPAND_PRMT) {
2292                 free((char*)cmdedit_prompt);
2293                 cmdedit_prompt = ckstrdup(s);
2294                 return;
2295         }
2296         cmdedit_prompt = s;
2297 }
2298 #else
2299 static void
2300 putprompt(const char *s)
2301 {
2302         out2str(s);
2303 }
2304 #endif
2305
2306 #if ENABLE_ASH_EXPAND_PRMT
2307 /* expandstr() needs parsing machinery, so it is far away ahead... */
2308 static const char *expandstr(const char *ps);
2309 #else
2310 #define expandstr(s) s
2311 #endif
2312
2313 static void
2314 setprompt(int whichprompt)
2315 {
2316         const char *prompt;
2317 #if ENABLE_ASH_EXPAND_PRMT
2318         struct stackmark smark;
2319 #endif
2320
2321         needprompt = 0;
2322
2323         switch (whichprompt) {
2324         case 1:
2325                 prompt = ps1val();
2326                 break;
2327         case 2:
2328                 prompt = ps2val();
2329                 break;
2330         default:                        /* 0 */
2331                 prompt = nullstr;
2332         }
2333 #if ENABLE_ASH_EXPAND_PRMT
2334         setstackmark(&smark);
2335         stalloc(stackblocksize());
2336 #endif
2337         putprompt(expandstr(prompt));
2338 #if ENABLE_ASH_EXPAND_PRMT
2339         popstackmark(&smark);
2340 #endif
2341 }
2342
2343
2344 /* ============ The cd and pwd commands */
2345
2346 #define CD_PHYSICAL 1
2347 #define CD_PRINT 2
2348
2349 static int docd(const char *, int);
2350
2351 static int
2352 cdopt(void)
2353 {
2354         int flags = 0;
2355         int i, j;
2356
2357         j = 'L';
2358         while ((i = nextopt("LP"))) {
2359                 if (i != j) {
2360                         flags ^= CD_PHYSICAL;
2361                         j = i;
2362                 }
2363         }
2364
2365         return flags;
2366 }
2367
2368 /*
2369  * Update curdir (the name of the current directory) in response to a
2370  * cd command.
2371  */
2372 static const char *
2373 updatepwd(const char *dir)
2374 {
2375         char *new;
2376         char *p;
2377         char *cdcomppath;
2378         const char *lim;
2379
2380         cdcomppath = ststrdup(dir);
2381         STARTSTACKSTR(new);
2382         if (*dir != '/') {
2383                 if (curdir == nullstr)
2384                         return 0;
2385                 new = stack_putstr(curdir, new);
2386         }
2387         new = makestrspace(strlen(dir) + 2, new);
2388         lim = (char *)stackblock() + 1;
2389         if (*dir != '/') {
2390                 if (new[-1] != '/')
2391                         USTPUTC('/', new);
2392                 if (new > lim && *lim == '/')
2393                         lim++;
2394         } else {
2395                 USTPUTC('/', new);
2396                 cdcomppath++;
2397                 if (dir[1] == '/' && dir[2] != '/') {
2398                         USTPUTC('/', new);
2399                         cdcomppath++;
2400                         lim++;
2401                 }
2402         }
2403         p = strtok(cdcomppath, "/");
2404         while (p) {
2405                 switch (*p) {
2406                 case '.':
2407                         if (p[1] == '.' && p[2] == '\0') {
2408                                 while (new > lim) {
2409                                         STUNPUTC(new);
2410                                         if (new[-1] == '/')
2411                                                 break;
2412                                 }
2413                                 break;
2414                         }
2415                         if (p[1] == '\0')
2416                                 break;
2417                         /* fall through */
2418                 default:
2419                         new = stack_putstr(p, new);
2420                         USTPUTC('/', new);
2421                 }
2422                 p = strtok(0, "/");
2423         }
2424         if (new > lim)
2425                 STUNPUTC(new);
2426         *new = 0;
2427         return stackblock();
2428 }
2429
2430 /*
2431  * Find out what the current directory is. If we already know the current
2432  * directory, this routine returns immediately.
2433  */
2434 static char *
2435 getpwd(void)
2436 {
2437         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2438         return dir ? dir : nullstr;
2439 }
2440
2441 static void
2442 setpwd(const char *val, int setold)
2443 {
2444         char *oldcur, *dir;
2445
2446         oldcur = dir = curdir;
2447
2448         if (setold) {
2449                 setvar("OLDPWD", oldcur, VEXPORT);
2450         }
2451         INT_OFF;
2452         if (physdir != nullstr) {
2453                 if (physdir != oldcur)
2454                         free(physdir);
2455                 physdir = nullstr;
2456         }
2457         if (oldcur == val || !val) {
2458                 char *s = getpwd();
2459                 physdir = s;
2460                 if (!val)
2461                         dir = s;
2462         } else
2463                 dir = ckstrdup(val);
2464         if (oldcur != dir && oldcur != nullstr) {
2465                 free(oldcur);
2466         }
2467         curdir = dir;
2468         INT_ON;
2469         setvar("PWD", dir, VEXPORT);
2470 }
2471
2472 static void hashcd(void);
2473
2474 /*
2475  * Actually do the chdir.  We also call hashcd to let the routines in exec.c
2476  * know that the current directory has changed.
2477  */
2478 static int
2479 docd(const char *dest, int flags)
2480 {
2481         const char *dir = 0;
2482         int err;
2483
2484         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2485
2486         INT_OFF;
2487         if (!(flags & CD_PHYSICAL)) {
2488                 dir = updatepwd(dest);
2489                 if (dir)
2490                         dest = dir;
2491         }
2492         err = chdir(dest);
2493         if (err)
2494                 goto out;
2495         setpwd(dir, 1);
2496         hashcd();
2497  out:
2498         INT_ON;
2499         return err;
2500 }
2501
2502 static int
2503 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2504 {
2505         const char *dest;
2506         const char *path;
2507         const char *p;
2508         char c;
2509         struct stat statb;
2510         int flags;
2511
2512         flags = cdopt();
2513         dest = *argptr;
2514         if (!dest)
2515                 dest = bltinlookup(homestr);
2516         else if (LONE_DASH(dest)) {
2517                 dest = bltinlookup("OLDPWD");
2518                 flags |= CD_PRINT;
2519         }
2520         if (!dest)
2521                 dest = nullstr;
2522         if (*dest == '/')
2523                 goto step7;
2524         if (*dest == '.') {
2525                 c = dest[1];
2526  dotdot:
2527                 switch (c) {
2528                 case '\0':
2529                 case '/':
2530                         goto step6;
2531                 case '.':
2532                         c = dest[2];
2533                         if (c != '.')
2534                                 goto dotdot;
2535                 }
2536         }
2537         if (!*dest)
2538                 dest = ".";
2539         path = bltinlookup("CDPATH");
2540         if (!path) {
2541  step6:
2542  step7:
2543                 p = dest;
2544                 goto docd;
2545         }
2546         do {
2547                 c = *path;
2548                 p = padvance(&path, dest);
2549                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2550                         if (c && c != ':')
2551                                 flags |= CD_PRINT;
2552  docd:
2553                         if (!docd(p, flags))
2554                                 goto out;
2555                         break;
2556                 }
2557         } while (path);
2558         ash_msg_and_raise_error("can't cd to %s", dest);
2559         /* NOTREACHED */
2560  out:
2561         if (flags & CD_PRINT)
2562                 out1fmt(snlfmt, curdir);
2563         return 0;
2564 }
2565
2566 static int
2567 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2568 {
2569         int flags;
2570         const char *dir = curdir;
2571
2572         flags = cdopt();
2573         if (flags) {
2574                 if (physdir == nullstr)
2575                         setpwd(dir, 0);
2576                 dir = physdir;
2577         }
2578         out1fmt(snlfmt, dir);
2579         return 0;
2580 }
2581
2582
2583 /* ============ ... */
2584
2585
2586 #define IBUFSIZ COMMON_BUFSIZE
2587 /* buffer for top level input file */
2588 #define basebuf bb_common_bufsiz1
2589
2590 /* Syntax classes */
2591 #define CWORD     0             /* character is nothing special */
2592 #define CNL       1             /* newline character */
2593 #define CBACK     2             /* a backslash character */
2594 #define CSQUOTE   3             /* single quote */
2595 #define CDQUOTE   4             /* double quote */
2596 #define CENDQUOTE 5             /* a terminating quote */
2597 #define CBQUOTE   6             /* backwards single quote */
2598 #define CVAR      7             /* a dollar sign */
2599 #define CENDVAR   8             /* a '}' character */
2600 #define CLP       9             /* a left paren in arithmetic */
2601 #define CRP      10             /* a right paren in arithmetic */
2602 #define CENDFILE 11             /* end of file */
2603 #define CCTL     12             /* like CWORD, except it must be escaped */
2604 #define CSPCL    13             /* these terminate a word */
2605 #define CIGN     14             /* character should be ignored */
2606
2607 #if ENABLE_ASH_ALIAS
2608 #define SYNBASE       130
2609 #define PEOF         -130
2610 #define PEOA         -129
2611 #define PEOA_OR_PEOF PEOA
2612 #else
2613 #define SYNBASE       129
2614 #define PEOF         -129
2615 #define PEOA_OR_PEOF PEOF
2616 #endif
2617
2618 /* number syntax index */
2619 #define BASESYNTAX 0    /* not in quotes */
2620 #define DQSYNTAX   1    /* in double quotes */
2621 #define SQSYNTAX   2    /* in single quotes */
2622 #define ARISYNTAX  3    /* in arithmetic */
2623 #define PSSYNTAX   4    /* prompt */
2624
2625 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2626 #define USE_SIT_FUNCTION
2627 #endif
2628
2629 #if ENABLE_ASH_MATH_SUPPORT
2630 static const char S_I_T[][4] = {
2631 #if ENABLE_ASH_ALIAS
2632         { CSPCL, CIGN, CIGN, CIGN },            /* 0, PEOA */
2633 #endif
2634         { CSPCL, CWORD, CWORD, CWORD },         /* 1, ' ' */
2635         { CNL, CNL, CNL, CNL },                 /* 2, \n */
2636         { CWORD, CCTL, CCTL, CWORD },           /* 3, !*-/:=?[]~ */
2637         { CDQUOTE, CENDQUOTE, CWORD, CWORD },   /* 4, '"' */
2638         { CVAR, CVAR, CWORD, CVAR },            /* 5, $ */
2639         { CSQUOTE, CWORD, CENDQUOTE, CWORD },   /* 6, "'" */
2640         { CSPCL, CWORD, CWORD, CLP },           /* 7, ( */
2641         { CSPCL, CWORD, CWORD, CRP },           /* 8, ) */
2642         { CBACK, CBACK, CCTL, CBACK },          /* 9, \ */
2643         { CBQUOTE, CBQUOTE, CWORD, CBQUOTE },   /* 10, ` */
2644         { CENDVAR, CENDVAR, CWORD, CENDVAR },   /* 11, } */
2645 #ifndef USE_SIT_FUNCTION
2646         { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2647         { CWORD, CWORD, CWORD, CWORD },         /* 13, 0-9A-Za-z */
2648         { CCTL, CCTL, CCTL, CCTL }              /* 14, CTLESC ... */
2649 #endif
2650 };
2651 #else
2652 static const char S_I_T[][3] = {
2653 #if ENABLE_ASH_ALIAS
2654         { CSPCL, CIGN, CIGN },                  /* 0, PEOA */
2655 #endif
2656         { CSPCL, CWORD, CWORD },                /* 1, ' ' */
2657         { CNL, CNL, CNL },                      /* 2, \n */
2658         { CWORD, CCTL, CCTL },                  /* 3, !*-/:=?[]~ */
2659         { CDQUOTE, CENDQUOTE, CWORD },          /* 4, '"' */
2660         { CVAR, CVAR, CWORD },                  /* 5, $ */
2661         { CSQUOTE, CWORD, CENDQUOTE },          /* 6, "'" */
2662         { CSPCL, CWORD, CWORD },                /* 7, ( */
2663         { CSPCL, CWORD, CWORD },                /* 8, ) */
2664         { CBACK, CBACK, CCTL },                 /* 9, \ */
2665         { CBQUOTE, CBQUOTE, CWORD },            /* 10, ` */
2666         { CENDVAR, CENDVAR, CWORD },            /* 11, } */
2667 #ifndef USE_SIT_FUNCTION
2668         { CENDFILE, CENDFILE, CENDFILE },       /* 12, PEOF */
2669         { CWORD, CWORD, CWORD },                /* 13, 0-9A-Za-z */
2670         { CCTL, CCTL, CCTL }                    /* 14, CTLESC ... */
2671 #endif
2672 };
2673 #endif /* ASH_MATH_SUPPORT */
2674
2675 #ifdef USE_SIT_FUNCTION
2676
2677 static int
2678 SIT(int c, int syntax)
2679 {
2680         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2681 #if ENABLE_ASH_ALIAS
2682         static const char syntax_index_table[] ALIGN1 = {
2683                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2684                 7, 8, 3, 3, 3, 3, 1, 1,         /* "()*-/:;<" */
2685                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2686                 11, 3                           /* "}~" */
2687         };
2688 #else
2689         static const char syntax_index_table[] ALIGN1 = {
2690                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2691                 6, 7, 2, 2, 2, 2, 0, 0,         /* "()*-/:;<" */
2692                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2693                 10, 2                           /* "}~" */
2694         };
2695 #endif
2696         const char *s;
2697         int indx;
2698
2699         if (c == PEOF)          /* 2^8+2 */
2700                 return CENDFILE;
2701 #if ENABLE_ASH_ALIAS
2702         if (c == PEOA)          /* 2^8+1 */
2703                 indx = 0;
2704         else
2705 #endif
2706
2707         if ((unsigned char)c >= (unsigned char)(CTLESC)
2708          && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2709         ) {
2710                 return CCTL;
2711         }
2712         s = strchrnul(spec_symbls, c);
2713         if (*s == '\0')
2714                 return CWORD;
2715         indx = syntax_index_table[s - spec_symbls];
2716         return S_I_T[indx][syntax];
2717 }
2718
2719 #else   /* !USE_SIT_FUNCTION */
2720
2721 #if ENABLE_ASH_ALIAS
2722 #define CSPCL_CIGN_CIGN_CIGN                     0
2723 #define CSPCL_CWORD_CWORD_CWORD                  1
2724 #define CNL_CNL_CNL_CNL                          2
2725 #define CWORD_CCTL_CCTL_CWORD                    3
2726 #define CDQUOTE_CENDQUOTE_CWORD_CWORD            4
2727 #define CVAR_CVAR_CWORD_CVAR                     5
2728 #define CSQUOTE_CWORD_CENDQUOTE_CWORD            6
2729 #define CSPCL_CWORD_CWORD_CLP                    7
2730 #define CSPCL_CWORD_CWORD_CRP                    8
2731 #define CBACK_CBACK_CCTL_CBACK                   9
2732 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE           10
2733 #define CENDVAR_CENDVAR_CWORD_CENDVAR           11
2734 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE     12
2735 #define CWORD_CWORD_CWORD_CWORD                 13
2736 #define CCTL_CCTL_CCTL_CCTL                     14
2737 #else
2738 #define CSPCL_CWORD_CWORD_CWORD                  0
2739 #define CNL_CNL_CNL_CNL                          1
2740 #define CWORD_CCTL_CCTL_CWORD                    2
2741 #define CDQUOTE_CENDQUOTE_CWORD_CWORD            3
2742 #define CVAR_CVAR_CWORD_CVAR                     4
2743 #define CSQUOTE_CWORD_CENDQUOTE_CWORD            5
2744 #define CSPCL_CWORD_CWORD_CLP                    6
2745 #define CSPCL_CWORD_CWORD_CRP                    7
2746 #define CBACK_CBACK_CCTL_CBACK                   8
2747 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE            9
2748 #define CENDVAR_CENDVAR_CWORD_CENDVAR           10
2749 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE     11
2750 #define CWORD_CWORD_CWORD_CWORD                 12
2751 #define CCTL_CCTL_CCTL_CCTL                     13
2752 #endif
2753
2754 static const char syntax_index_table[258] = {
2755         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2756         /*   0  PEOF */      CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2757 #if ENABLE_ASH_ALIAS
2758         /*   1  PEOA */      CSPCL_CIGN_CIGN_CIGN,
2759 #endif
2760         /*   2  -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2761         /*   3  -127 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
2762         /*   4  -126 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
2763         /*   5  -125 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
2764         /*   6  -124 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
2765         /*   7  -123 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
2766         /*   8  -122 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
2767         /*   9  -121 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
2768         /*  10  -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2769         /*  11  -119      */ CWORD_CWORD_CWORD_CWORD,
2770         /*  12  -118      */ CWORD_CWORD_CWORD_CWORD,
2771         /*  13  -117      */ CWORD_CWORD_CWORD_CWORD,
2772         /*  14  -116      */ CWORD_CWORD_CWORD_CWORD,
2773         /*  15  -115      */ CWORD_CWORD_CWORD_CWORD,
2774         /*  16  -114      */ CWORD_CWORD_CWORD_CWORD,
2775         /*  17  -113      */ CWORD_CWORD_CWORD_CWORD,
2776         /*  18  -112      */ CWORD_CWORD_CWORD_CWORD,
2777         /*  19  -111      */ CWORD_CWORD_CWORD_CWORD,
2778         /*  20  -110      */ CWORD_CWORD_CWORD_CWORD,
2779         /*  21  -109      */ CWORD_CWORD_CWORD_CWORD,
2780         /*  22  -108      */ CWORD_CWORD_CWORD_CWORD,
2781         /*  23  -107      */ CWORD_CWORD_CWORD_CWORD,
2782         /*  24  -106      */ CWORD_CWORD_CWORD_CWORD,
2783         /*  25  -105      */ CWORD_CWORD_CWORD_CWORD,
2784         /*  26  -104      */ CWORD_CWORD_CWORD_CWORD,
2785         /*  27  -103      */ CWORD_CWORD_CWORD_CWORD,
2786         /*  28  -102      */ CWORD_CWORD_CWORD_CWORD,
2787         /*  29  -101      */ CWORD_CWORD_CWORD_CWORD,
2788         /*  30  -100      */ CWORD_CWORD_CWORD_CWORD,
2789         /*  31   -99      */ CWORD_CWORD_CWORD_CWORD,
2790         /*  32   -98      */ CWORD_CWORD_CWORD_CWORD,
2791         /*  33   -97      */ CWORD_CWORD_CWORD_CWORD,
2792         /*  34   -96      */ CWORD_CWORD_CWORD_CWORD,
2793         /*  35   -95      */ CWORD_CWORD_CWORD_CWORD,
2794         /*  36   -94      */ CWORD_CWORD_CWORD_CWORD,
2795         /*  37   -93      */ CWORD_CWORD_CWORD_CWORD,
2796         /*  38   -92      */ CWORD_CWORD_CWORD_CWORD,
2797         /*  39   -91      */ CWORD_CWORD_CWORD_CWORD,
2798         /*  40   -90      */ CWORD_CWORD_CWORD_CWORD,
2799         /*  41   -89      */ CWORD_CWORD_CWORD_CWORD,
2800         /*  42   -88      */ CWORD_CWORD_CWORD_CWORD,
2801         /*  43   -87      */ CWORD_CWORD_CWORD_CWORD,
2802         /*  44   -86      */ CWORD_CWORD_CWORD_CWORD,
2803         /*  45   -85      */ CWORD_CWORD_CWORD_CWORD,
2804         /*  46   -84      */ CWORD_CWORD_CWORD_CWORD,
2805         /*  47   -83      */ CWORD_CWORD_CWORD_CWORD,
2806         /*  48   -82      */ CWORD_CWORD_CWORD_CWORD,
2807         /*  49   -81      */ CWORD_CWORD_CWORD_CWORD,
2808         /*  50   -80      */ CWORD_CWORD_CWORD_CWORD,
2809         /*  51   -79      */ CWORD_CWORD_CWORD_CWORD,
2810         /*  52   -78      */ CWORD_CWORD_CWORD_CWORD,
2811         /*  53   -77      */ CWORD_CWORD_CWORD_CWORD,
2812         /*  54   -76      */ CWORD_CWORD_CWORD_CWORD,
2813         /*  55   -75      */ CWORD_CWORD_CWORD_CWORD,
2814         /*  56   -74      */ CWORD_CWORD_CWORD_CWORD,
2815         /*  57   -73      */ CWORD_CWORD_CWORD_CWORD,
2816         /*  58   -72      */ CWORD_CWORD_CWORD_CWORD,
2817         /*  59   -71      */ CWORD_CWORD_CWORD_CWORD,
2818         /*  60   -70      */ CWORD_CWORD_CWORD_CWORD,
2819         /*  61   -69      */ CWORD_CWORD_CWORD_CWORD,
2820         /*  62   -68      */ CWORD_CWORD_CWORD_CWORD,
2821         /*  63   -67      */ CWORD_CWORD_CWORD_CWORD,
2822         /*  64   -66      */ CWORD_CWORD_CWORD_CWORD,
2823         /*  65   -65      */ CWORD_CWORD_CWORD_CWORD,
2824         /*  66   -64      */ CWORD_CWORD_CWORD_CWORD,
2825         /*  67   -63      */ CWORD_CWORD_CWORD_CWORD,
2826         /*  68   -62      */ CWORD_CWORD_CWORD_CWORD,
2827         /*  69   -61      */ CWORD_CWORD_CWORD_CWORD,
2828         /*  70   -60      */ CWORD_CWORD_CWORD_CWORD,
2829         /*  71   -59      */ CWORD_CWORD_CWORD_CWORD,
2830         /*  72   -58      */ CWORD_CWORD_CWORD_CWORD,
2831         /*  73   -57      */ CWORD_CWORD_CWORD_CWORD,
2832         /*  74   -56      */ CWORD_CWORD_CWORD_CWORD,
2833         /*  75   -55      */ CWORD_CWORD_CWORD_CWORD,
2834         /*  76   -54      */ CWORD_CWORD_CWORD_CWORD,
2835         /*  77   -53      */ CWORD_CWORD_CWORD_CWORD,
2836         /*  78   -52      */ CWORD_CWORD_CWORD_CWORD,
2837         /*  79   -51      */ CWORD_CWORD_CWORD_CWORD,
2838         /*  80   -50      */ CWORD_CWORD_CWORD_CWORD,
2839         /*  81   -49      */ CWORD_CWORD_CWORD_CWORD,
2840         /*  82   -48      */ CWORD_CWORD_CWORD_CWORD,
2841         /*  83   -47      */ CWORD_CWORD_CWORD_CWORD,
2842         /*  84   -46      */ CWORD_CWORD_CWORD_CWORD,
2843         /*  85   -45      */ CWORD_CWORD_CWORD_CWORD,
2844         /*  86   -44      */ CWORD_CWORD_CWORD_CWORD,
2845         /*  87   -43      */ CWORD_CWORD_CWORD_CWORD,
2846         /*  88   -42      */ CWORD_CWORD_CWORD_CWORD,
2847         /*  89   -41      */ CWORD_CWORD_CWORD_CWORD,
2848         /*  90   -40      */ CWORD_CWORD_CWORD_CWORD,
2849         /*  91   -39      */ CWORD_CWORD_CWORD_CWORD,
2850         /*  92   -38      */ CWORD_CWORD_CWORD_CWORD,
2851         /*  93   -37      */ CWORD_CWORD_CWORD_CWORD,
2852         /*  94   -36      */ CWORD_CWORD_CWORD_CWORD,
2853         /*  95   -35      */ CWORD_CWORD_CWORD_CWORD,
2854         /*  96   -34      */ CWORD_CWORD_CWORD_CWORD,
2855         /*  97   -33      */ CWORD_CWORD_CWORD_CWORD,
2856         /*  98   -32      */ CWORD_CWORD_CWORD_CWORD,
2857         /*  99   -31      */ CWORD_CWORD_CWORD_CWORD,
2858         /* 100   -30      */ CWORD_CWORD_CWORD_CWORD,
2859         /* 101   -29      */ CWORD_CWORD_CWORD_CWORD,
2860         /* 102   -28      */ CWORD_CWORD_CWORD_CWORD,
2861         /* 103   -27      */ CWORD_CWORD_CWORD_CWORD,
2862         /* 104   -26      */ CWORD_CWORD_CWORD_CWORD,
2863         /* 105   -25      */ CWORD_CWORD_CWORD_CWORD,
2864         /* 106   -24      */ CWORD_CWORD_CWORD_CWORD,
2865         /* 107   -23      */ CWORD_CWORD_CWORD_CWORD,
2866         /* 108   -22      */ CWORD_CWORD_CWORD_CWORD,
2867         /* 109   -21      */ CWORD_CWORD_CWORD_CWORD,
2868         /* 110   -20      */ CWORD_CWORD_CWORD_CWORD,
2869         /* 111   -19      */ CWORD_CWORD_CWORD_CWORD,
2870         /* 112   -18      */ CWORD_CWORD_CWORD_CWORD,
2871         /* 113   -17      */ CWORD_CWORD_CWORD_CWORD,
2872         /* 114   -16      */ CWORD_CWORD_CWORD_CWORD,
2873         /* 115   -15      */ CWORD_CWORD_CWORD_CWORD,
2874         /* 116   -14      */ CWORD_CWORD_CWORD_CWORD,
2875         /* 117   -13      */ CWORD_CWORD_CWORD_CWORD,
2876         /* 118   -12      */ CWORD_CWORD_CWORD_CWORD,
2877         /* 119   -11      */ CWORD_CWORD_CWORD_CWORD,
2878         /* 120   -10      */ CWORD_CWORD_CWORD_CWORD,
2879         /* 121    -9      */ CWORD_CWORD_CWORD_CWORD,
2880         /* 122    -8      */ CWORD_CWORD_CWORD_CWORD,
2881         /* 123    -7      */ CWORD_CWORD_CWORD_CWORD,
2882         /* 124    -6      */ CWORD_CWORD_CWORD_CWORD,
2883         /* 125    -5      */ CWORD_CWORD_CWORD_CWORD,
2884         /* 126    -4      */ CWORD_CWORD_CWORD_CWORD,
2885         /* 127    -3      */ CWORD_CWORD_CWORD_CWORD,
2886         /* 128    -2      */ CWORD_CWORD_CWORD_CWORD,
2887         /* 129    -1      */ CWORD_CWORD_CWORD_CWORD,
2888         /* 130     0      */ CWORD_CWORD_CWORD_CWORD,
2889         /* 131     1      */ CWORD_CWORD_CWORD_CWORD,
2890         /* 132     2      */ CWORD_CWORD_CWORD_CWORD,
2891         /* 133     3      */ CWORD_CWORD_CWORD_CWORD,
2892         /* 134     4      */ CWORD_CWORD_CWORD_CWORD,
2893         /* 135     5      */ CWORD_CWORD_CWORD_CWORD,
2894         /* 136     6      */ CWORD_CWORD_CWORD_CWORD,
2895         /* 137     7      */ CWORD_CWORD_CWORD_CWORD,
2896         /* 138     8      */ CWORD_CWORD_CWORD_CWORD,
2897         /* 139     9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2898         /* 140    10 "\n" */ CNL_CNL_CNL_CNL,
2899         /* 141    11      */ CWORD_CWORD_CWORD_CWORD,
2900         /* 142    12      */ CWORD_CWORD_CWORD_CWORD,
2901         /* 143    13      */ CWORD_CWORD_CWORD_CWORD,
2902         /* 144    14      */ CWORD_CWORD_CWORD_CWORD,
2903         /* 145    15      */ CWORD_CWORD_CWORD_CWORD,
2904         /* 146    16      */ CWORD_CWORD_CWORD_CWORD,
2905         /* 147    17      */ CWORD_CWORD_CWORD_CWORD,
2906         /* 148    18      */ CWORD_CWORD_CWORD_CWORD,
2907         /* 149    19      */ CWORD_CWORD_CWORD_CWORD,
2908         /* 150    20      */ CWORD_CWORD_CWORD_CWORD,
2909         /* 151    21      */ CWORD_CWORD_CWORD_CWORD,
2910         /* 152    22      */ CWORD_CWORD_CWORD_CWORD,
2911         /* 153    23      */ CWORD_CWORD_CWORD_CWORD,
2912         /* 154    24      */ CWORD_CWORD_CWORD_CWORD,
2913         /* 155    25      */ CWORD_CWORD_CWORD_CWORD,
2914         /* 156    26      */ CWORD_CWORD_CWORD_CWORD,
2915         /* 157    27      */ CWORD_CWORD_CWORD_CWORD,
2916         /* 158    28      */ CWORD_CWORD_CWORD_CWORD,
2917         /* 159    29      */ CWORD_CWORD_CWORD_CWORD,
2918         /* 160    30      */ CWORD_CWORD_CWORD_CWORD,
2919         /* 161    31      */ CWORD_CWORD_CWORD_CWORD,
2920         /* 162    32  " " */ CSPCL_CWORD_CWORD_CWORD,
2921         /* 163    33  "!" */ CWORD_CCTL_CCTL_CWORD,
2922         /* 164    34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2923         /* 165    35  "#" */ CWORD_CWORD_CWORD_CWORD,
2924         /* 166    36  "$" */ CVAR_CVAR_CWORD_CVAR,
2925         /* 167    37  "%" */ CWORD_CWORD_CWORD_CWORD,
2926         /* 168    38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2927         /* 169    39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2928         /* 170    40  "(" */ CSPCL_CWORD_CWORD_CLP,
2929         /* 171    41  ")" */ CSPCL_CWORD_CWORD_CRP,
2930         /* 172    42  "*" */ CWORD_CCTL_CCTL_CWORD,
2931         /* 173    43  "+" */ CWORD_CWORD_CWORD_CWORD,
2932         /* 174    44  "," */ CWORD_CWORD_CWORD_CWORD,
2933         /* 175    45  "-" */ CWORD_CCTL_CCTL_CWORD,
2934         /* 176    46  "." */ CWORD_CWORD_CWORD_CWORD,
2935         /* 177    47  "/" */ CWORD_CCTL_CCTL_CWORD,
2936         /* 178    48  "0" */ CWORD_CWORD_CWORD_CWORD,
2937         /* 179    49  "1" */ CWORD_CWORD_CWORD_CWORD,
2938         /* 180    50  "2" */ CWORD_CWORD_CWORD_CWORD,
2939         /* 181    51  "3" */ CWORD_CWORD_CWORD_CWORD,
2940         /* 182    52  "4" */ CWORD_CWORD_CWORD_CWORD,
2941         /* 183    53  "5" */ CWORD_CWORD_CWORD_CWORD,
2942         /* 184    54  "6" */ CWORD_CWORD_CWORD_CWORD,
2943         /* 185    55  "7" */ CWORD_CWORD_CWORD_CWORD,
2944         /* 186    56  "8" */ CWORD_CWORD_CWORD_CWORD,
2945         /* 187    57  "9" */ CWORD_CWORD_CWORD_CWORD,
2946         /* 188    58  ":" */ CWORD_CCTL_CCTL_CWORD,
2947         /* 189    59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2948         /* 190    60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2949         /* 191    61  "=" */ CWORD_CCTL_CCTL_CWORD,
2950         /* 192    62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2951         /* 193    63  "?" */ CWORD_CCTL_CCTL_CWORD,
2952         /* 194    64  "@" */ CWORD_CWORD_CWORD_CWORD,
2953         /* 195    65  "A" */ CWORD_CWORD_CWORD_CWORD,
2954         /* 196    66  "B" */ CWORD_CWORD_CWORD_CWORD,
2955         /* 197    67  "C" */ CWORD_CWORD_CWORD_CWORD,
2956         /* 198    68  "D" */ CWORD_CWORD_CWORD_CWORD,
2957         /* 199    69  "E" */ CWORD_CWORD_CWORD_CWORD,
2958         /* 200    70  "F" */ CWORD_CWORD_CWORD_CWORD,
2959         /* 201    71  "G" */ CWORD_CWORD_CWORD_CWORD,
2960         /* 202    72  "H" */ CWORD_CWORD_CWORD_CWORD,
2961         /* 203    73  "I" */ CWORD_CWORD_CWORD_CWORD,
2962         /* 204    74  "J" */ CWORD_CWORD_CWORD_CWORD,
2963         /* 205    75  "K" */ CWORD_CWORD_CWORD_CWORD,
2964         /* 206    76  "L" */ CWORD_CWORD_CWORD_CWORD,
2965         /* 207    77  "M" */ CWORD_CWORD_CWORD_CWORD,
2966         /* 208    78  "N" */ CWORD_CWORD_CWORD_CWORD,
2967         /* 209    79  "O" */ CWORD_CWORD_CWORD_CWORD,
2968         /* 210    80  "P" */ CWORD_CWORD_CWORD_CWORD,
2969         /* 211    81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2970         /* 212    82  "R" */ CWORD_CWORD_CWORD_CWORD,
2971         /* 213    83  "S" */ CWORD_CWORD_CWORD_CWORD,
2972         /* 214    84  "T" */ CWORD_CWORD_CWORD_CWORD,
2973         /* 215    85  "U" */ CWORD_CWORD_CWORD_CWORD,
2974         /* 216    86  "V" */ CWORD_CWORD_CWORD_CWORD,
2975         /* 217    87  "W" */ CWORD_CWORD_CWORD_CWORD,
2976         /* 218    88  "X" */ CWORD_CWORD_CWORD_CWORD,
2977         /* 219    89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2978         /* 220    90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2979         /* 221    91  "[" */ CWORD_CCTL_CCTL_CWORD,
2980         /* 222    92  "\" */ CBACK_CBACK_CCTL_CBACK,
2981         /* 223    93  "]" */ CWORD_CCTL_CCTL_CWORD,
2982         /* 224    94  "^" */ CWORD_CWORD_CWORD_CWORD,
2983         /* 225    95  "_" */ CWORD_CWORD_CWORD_CWORD,
2984         /* 226    96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2985         /* 227    97  "a" */ CWORD_CWORD_CWORD_CWORD,
2986         /* 228    98  "b" */ CWORD_CWORD_CWORD_CWORD,
2987         /* 229    99  "c" */ CWORD_CWORD_CWORD_CWORD,
2988         /* 230   100  "d" */ CWORD_CWORD_CWORD_CWORD,
2989         /* 231   101  "e" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 232   102  "f" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 233   103  "g" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 234   104  "h" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 235   105  "i" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 236   106  "j" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 237   107  "k" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 238   108  "l" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 239   109  "m" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 240   110  "n" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 241   111  "o" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 242   112  "p" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 243   113  "q" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 244   114  "r" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 245   115  "s" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 246   116  "t" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 247   117  "u" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 248   118  "v" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 249   119  "w" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 250   120  "x" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 251   121  "y" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 252   122  "z" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 253   123  "{" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 254   124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3013         /* 255   125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3014         /* 256   126  "~" */ CWORD_CCTL_CCTL_CWORD,
3015         /* 257   127      */ CWORD_CWORD_CWORD_CWORD,
3016 };
3017
3018 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
3019
3020 #endif  /* USE_SIT_FUNCTION */
3021
3022
3023 /* ============ Alias handling */
3024
3025 #if ENABLE_ASH_ALIAS
3026
3027 #define ALIASINUSE 1
3028 #define ALIASDEAD  2
3029
3030 struct alias {
3031         struct alias *next;
3032         char *name;
3033         char *val;
3034         int flag;
3035 };
3036
3037
3038 static struct alias **atab; // [ATABSIZE];
3039 #define INIT_G_alias() do { \
3040         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3041 } while (0)
3042
3043
3044 static struct alias **
3045 __lookupalias(const char *name) {
3046         unsigned int hashval;
3047         struct alias **app;
3048         const char *p;
3049         unsigned int ch;
3050
3051         p = name;
3052
3053         ch = (unsigned char)*p;
3054         hashval = ch << 4;
3055         while (ch) {
3056                 hashval += ch;
3057                 ch = (unsigned char)*++p;
3058         }
3059         app = &atab[hashval % ATABSIZE];
3060
3061         for (; *app; app = &(*app)->next) {
3062                 if (strcmp(name, (*app)->name) == 0) {
3063                         break;
3064                 }
3065         }
3066
3067         return app;
3068 }
3069
3070 static struct alias *
3071 lookupalias(const char *name, int check)
3072 {
3073         struct alias *ap = *__lookupalias(name);
3074
3075         if (check && ap && (ap->flag & ALIASINUSE))
3076                 return NULL;
3077         return ap;
3078 }
3079
3080 static struct alias *
3081 freealias(struct alias *ap)
3082 {
3083         struct alias *next;
3084
3085         if (ap->flag & ALIASINUSE) {
3086                 ap->flag |= ALIASDEAD;
3087                 return ap;
3088         }
3089
3090         next = ap->next;
3091         free(ap->name);
3092         free(ap->val);
3093         free(ap);
3094         return next;
3095 }
3096
3097 static void
3098 setalias(const char *name, const char *val)
3099 {
3100         struct alias *ap, **app;
3101
3102         app = __lookupalias(name);
3103         ap = *app;
3104         INT_OFF;
3105         if (ap) {
3106                 if (!(ap->flag & ALIASINUSE)) {
3107                         free(ap->val);
3108                 }
3109                 ap->val = ckstrdup(val);
3110                 ap->flag &= ~ALIASDEAD;
3111         } else {
3112                 /* not found */
3113                 ap = ckzalloc(sizeof(struct alias));
3114                 ap->name = ckstrdup(name);
3115                 ap->val = ckstrdup(val);
3116                 /*ap->flag = 0; - ckzalloc did it */
3117                 /*ap->next = NULL;*/
3118                 *app = ap;
3119         }
3120         INT_ON;
3121 }
3122
3123 static int
3124 unalias(const char *name)
3125 {
3126         struct alias **app;
3127
3128         app = __lookupalias(name);
3129
3130         if (*app) {
3131                 INT_OFF;
3132                 *app = freealias(*app);
3133                 INT_ON;
3134                 return 0;
3135         }
3136
3137         return 1;
3138 }
3139
3140 static void
3141 rmaliases(void)
3142 {
3143         struct alias *ap, **app;
3144         int i;
3145
3146         INT_OFF;
3147         for (i = 0; i < ATABSIZE; i++) {
3148                 app = &atab[i];
3149                 for (ap = *app; ap; ap = *app) {
3150                         *app = freealias(*app);
3151                         if (ap == *app) {
3152                                 app = &ap->next;
3153                         }
3154                 }
3155         }
3156         INT_ON;
3157 }
3158
3159 static void
3160 printalias(const struct alias *ap)
3161 {
3162         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3163 }
3164
3165 /*
3166  * TODO - sort output
3167  */
3168 static int
3169 aliascmd(int argc UNUSED_PARAM, char **argv)
3170 {
3171         char *n, *v;
3172         int ret = 0;
3173         struct alias *ap;
3174
3175         if (!argv[1]) {
3176                 int i;
3177
3178                 for (i = 0; i < ATABSIZE; i++) {
3179                         for (ap = atab[i]; ap; ap = ap->next) {
3180                                 printalias(ap);
3181                         }
3182                 }
3183                 return 0;
3184         }
3185         while ((n = *++argv) != NULL) {
3186                 v = strchr(n+1, '=');
3187                 if (v == NULL) { /* n+1: funny ksh stuff */
3188                         ap = *__lookupalias(n);
3189                         if (ap == NULL) {
3190                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3191                                 ret = 1;
3192                         } else
3193                                 printalias(ap);
3194                 } else {
3195                         *v++ = '\0';
3196                         setalias(n, v);
3197                 }
3198         }
3199
3200         return ret;
3201 }
3202
3203 static int
3204 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3205 {
3206         int i;
3207
3208         while ((i = nextopt("a")) != '\0') {
3209                 if (i == 'a') {
3210                         rmaliases();
3211                         return 0;
3212                 }
3213         }
3214         for (i = 0; *argptr; argptr++) {
3215                 if (unalias(*argptr)) {
3216                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3217                         i = 1;
3218                 }
3219         }
3220
3221         return i;
3222 }
3223
3224 #endif /* ASH_ALIAS */
3225
3226
3227 /* ============ jobs.c */
3228
3229 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3230 #define FORK_FG 0
3231 #define FORK_BG 1
3232 #define FORK_NOJOB 2
3233
3234 /* mode flags for showjob(s) */
3235 #define SHOW_PGID       0x01    /* only show pgid - for jobs -p */
3236 #define SHOW_PID        0x04    /* include process pid */
3237 #define SHOW_CHANGED    0x08    /* only jobs whose state has changed */
3238
3239 /*
3240  * A job structure contains information about a job.  A job is either a
3241  * single process or a set of processes contained in a pipeline.  In the
3242  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3243  * array of pids.
3244  */
3245
3246 struct procstat {
3247         pid_t   pid;            /* process id */
3248         int     status;         /* last process status from wait() */
3249         char    *cmd;           /* text of command being run */
3250 };
3251
3252 struct job {
3253         struct procstat ps0;    /* status of process */
3254         struct procstat *ps;    /* status or processes when more than one */
3255 #if JOBS
3256         int stopstatus;         /* status of a stopped job */
3257 #endif
3258         uint32_t
3259                 nprocs: 16,     /* number of processes */
3260                 state: 8,
3261 #define JOBRUNNING      0       /* at least one proc running */
3262 #define JOBSTOPPED      1       /* all procs are stopped */
3263 #define JOBDONE         2       /* all procs are completed */
3264 #if JOBS
3265                 sigint: 1,      /* job was killed by SIGINT */
3266                 jobctl: 1,      /* job running under job control */
3267 #endif
3268                 waited: 1,      /* true if this entry has been waited for */
3269                 used: 1,        /* true if this entry is in used */
3270                 changed: 1;     /* true if status has changed */
3271         struct job *prev_job;   /* previous job */
3272 };
3273
3274 static struct job *makejob(/*union node *,*/ int);
3275 #if !JOBS
3276 #define forkshell(job, node, mode) forkshell(job, mode)
3277 #endif
3278 static int forkshell(struct job *, union node *, int);
3279 static int waitforjob(struct job *);
3280
3281 #if !JOBS
3282 enum { doing_jobctl = 0 };
3283 #define setjobctl(on) do {} while (0)
3284 #else
3285 static smallint doing_jobctl; //references:8
3286 static void setjobctl(int);
3287 #endif
3288
3289 /*
3290  * Set the signal handler for the specified signal.  The routine figures
3291  * out what it should be set to.
3292  */
3293 static void
3294 setsignal(int signo)
3295 {
3296         char *t;
3297         char cur_act, new_act;
3298         struct sigaction act;
3299
3300         t = trap[signo];
3301         new_act = S_DFL;
3302         if (t != NULL) { /* trap for this sig is set */
3303                 new_act = S_CATCH;
3304                 if (t[0] == '\0') /* trap is "": ignore this sig */
3305                         new_act = S_IGN;
3306         }
3307
3308         if (rootshell && new_act == S_DFL) {
3309                 switch (signo) {
3310                 case SIGINT:
3311                         if (iflag || minusc || sflag == 0)
3312                                 new_act = S_CATCH;
3313                         break;
3314                 case SIGQUIT:
3315 #if DEBUG
3316                         if (debug)
3317                                 break;
3318 #endif
3319                         /* man bash:
3320                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3321                          * commands run by bash have signal handlers
3322                          * set to the values inherited by the shell
3323                          * from its parent". */
3324                         new_act = S_IGN;
3325                         break;
3326                 case SIGTERM:
3327                         if (iflag)
3328                                 new_act = S_IGN;
3329                         break;
3330 #if JOBS
3331                 case SIGTSTP:
3332                 case SIGTTOU:
3333                         if (mflag)
3334                                 new_act = S_IGN;
3335                         break;
3336 #endif
3337                 }
3338         }
3339 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3340 //whereas we have to restore it to what shell got on entry
3341 //from the parent. See comment above
3342
3343         t = &sigmode[signo - 1];
3344         cur_act = *t;
3345         if (cur_act == 0) {
3346                 /* current setting is not yet known */
3347                 if (sigaction(signo, NULL, &act)) {
3348                         /* pretend it worked; maybe we should give a warning,
3349                          * but other shells don't. We don't alter sigmode,
3350                          * so we retry every time.
3351                          * btw, in Linux it never fails. --vda */
3352                         return;
3353                 }
3354                 if (act.sa_handler == SIG_IGN) {
3355                         cur_act = S_HARD_IGN;
3356                         if (mflag
3357                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3358                         ) {
3359                                 cur_act = S_IGN;   /* don't hard ignore these */
3360                         }
3361                 }
3362         }
3363         if (cur_act == S_HARD_IGN || cur_act == new_act)
3364                 return;
3365
3366         act.sa_handler = SIG_DFL;
3367         switch (new_act) {
3368         case S_CATCH:
3369                 act.sa_handler = onsig;
3370                 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3371                 sigfillset(&act.sa_mask); /* ditto */
3372                 break;
3373         case S_IGN:
3374                 act.sa_handler = SIG_IGN;
3375                 break;
3376         }
3377         sigaction_set(signo, &act);
3378
3379         *t = new_act;
3380 }
3381
3382 /* mode flags for set_curjob */
3383 #define CUR_DELETE 2
3384 #define CUR_RUNNING 1
3385 #define CUR_STOPPED 0
3386
3387 /* mode flags for dowait */
3388 #define DOWAIT_NONBLOCK WNOHANG
3389 #define DOWAIT_BLOCK    0
3390
3391 #if JOBS
3392 /* pgrp of shell on invocation */
3393 static int initialpgrp; //references:2
3394 static int ttyfd = -1; //5
3395 #endif
3396 /* array of jobs */
3397 static struct job *jobtab; //5
3398 /* size of array */
3399 static unsigned njobs; //4
3400 /* current job */
3401 static struct job *curjob; //lots
3402 /* number of presumed living untracked jobs */
3403 static int jobless; //4
3404
3405 static void
3406 set_curjob(struct job *jp, unsigned mode)
3407 {
3408         struct job *jp1;
3409         struct job **jpp, **curp;
3410
3411         /* first remove from list */
3412         jpp = curp = &curjob;
3413         do {
3414                 jp1 = *jpp;
3415                 if (jp1 == jp)
3416                         break;
3417                 jpp = &jp1->prev_job;
3418         } while (1);
3419         *jpp = jp1->prev_job;
3420
3421         /* Then re-insert in correct position */
3422         jpp = curp;
3423         switch (mode) {
3424         default:
3425 #if DEBUG
3426                 abort();
3427 #endif
3428         case CUR_DELETE:
3429                 /* job being deleted */
3430                 break;
3431         case CUR_RUNNING:
3432                 /* newly created job or backgrounded job,
3433                    put after all stopped jobs. */
3434                 do {
3435                         jp1 = *jpp;
3436 #if JOBS
3437                         if (!jp1 || jp1->state != JOBSTOPPED)
3438 #endif
3439                                 break;
3440                         jpp = &jp1->prev_job;
3441                 } while (1);
3442                 /* FALLTHROUGH */
3443 #if JOBS
3444         case CUR_STOPPED:
3445 #endif
3446                 /* newly stopped job - becomes curjob */
3447                 jp->prev_job = *jpp;
3448                 *jpp = jp;
3449                 break;
3450         }
3451 }
3452
3453 #if JOBS || DEBUG
3454 static int
3455 jobno(const struct job *jp)
3456 {
3457         return jp - jobtab + 1;
3458 }
3459 #endif
3460
3461 /*
3462  * Convert a job name to a job structure.
3463  */
3464 #if !JOBS
3465 #define getjob(name, getctl) getjob(name)
3466 #endif
3467 static struct job *
3468 getjob(const char *name, int getctl)
3469 {
3470         struct job *jp;
3471         struct job *found;
3472         const char *err_msg = "No such job: %s";
3473         unsigned num;
3474         int c;
3475         const char *p;
3476         char *(*match)(const char *, const char *);
3477
3478         jp = curjob;
3479         p = name;
3480         if (!p)
3481                 goto currentjob;
3482
3483         if (*p != '%')
3484                 goto err;
3485
3486         c = *++p;
3487         if (!c)
3488                 goto currentjob;
3489
3490         if (!p[1]) {
3491                 if (c == '+' || c == '%') {
3492  currentjob:
3493                         err_msg = "No current job";
3494                         goto check;
3495                 }
3496                 if (c == '-') {
3497                         if (jp)
3498                                 jp = jp->prev_job;
3499                         err_msg = "No previous job";
3500  check:
3501                         if (!jp)
3502                                 goto err;
3503                         goto gotit;
3504                 }
3505         }
3506
3507         if (is_number(p)) {
3508 // TODO: number() instead? It does error checking...
3509                 num = atoi(p);
3510                 if (num < njobs) {
3511                         jp = jobtab + num - 1;
3512                         if (jp->used)
3513                                 goto gotit;
3514                         goto err;
3515                 }
3516         }
3517
3518         match = prefix;
3519         if (*p == '?') {
3520                 match = strstr;
3521                 p++;
3522         }
3523
3524         found = 0;
3525         while (1) {
3526                 if (!jp)
3527                         goto err;
3528                 if (match(jp->ps[0].cmd, p)) {
3529                         if (found)
3530                                 goto err;
3531                         found = jp;
3532                         err_msg = "%s: ambiguous";
3533                 }
3534                 jp = jp->prev_job;
3535         }
3536
3537  gotit:
3538 #if JOBS
3539         err_msg = "job %s not created under job control";
3540         if (getctl && jp->jobctl == 0)
3541                 goto err;
3542 #endif
3543         return jp;
3544  err:
3545         ash_msg_and_raise_error(err_msg, name);
3546 }
3547
3548 /*
3549  * Mark a job structure as unused.
3550  */
3551 static void
3552 freejob(struct job *jp)
3553 {
3554         struct procstat *ps;
3555         int i;
3556
3557         INT_OFF;
3558         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3559                 if (ps->cmd != nullstr)
3560                         free(ps->cmd);
3561         }
3562         if (jp->ps != &jp->ps0)
3563                 free(jp->ps);
3564         jp->used = 0;
3565         set_curjob(jp, CUR_DELETE);
3566         INT_ON;
3567 }
3568
3569 #if JOBS
3570 static void
3571 xtcsetpgrp(int fd, pid_t pgrp)
3572 {
3573         if (tcsetpgrp(fd, pgrp))
3574                 ash_msg_and_raise_error("can't set tty process group (%m)");
3575 }
3576
3577 /*
3578  * Turn job control on and off.
3579  *
3580  * Note:  This code assumes that the third arg to ioctl is a character
3581  * pointer, which is true on Berkeley systems but not System V.  Since
3582  * System V doesn't have job control yet, this isn't a problem now.
3583  *
3584  * Called with interrupts off.
3585  */
3586 static void
3587 setjobctl(int on)
3588 {
3589         int fd;
3590         int pgrp;
3591
3592         if (on == doing_jobctl || rootshell == 0)
3593                 return;
3594         if (on) {
3595                 int ofd;
3596                 ofd = fd = open(_PATH_TTY, O_RDWR);
3597                 if (fd < 0) {
3598         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3599          * That sometimes helps to acquire controlling tty.
3600          * Obviously, a workaround for bugs when someone
3601          * failed to provide a controlling tty to bash! :) */
3602                         fd = 2;
3603                         while (!isatty(fd))
3604                                 if (--fd < 0)
3605                                         goto out;
3606                 }
3607                 fd = fcntl(fd, F_DUPFD, 10);
3608                 if (ofd >= 0)
3609                         close(ofd);
3610                 if (fd < 0)
3611                         goto out;
3612                 /* fd is a tty at this point */
3613                 close_on_exec_on(fd);
3614                 do { /* while we are in the background */
3615                         pgrp = tcgetpgrp(fd);
3616                         if (pgrp < 0) {
3617  out:
3618                                 ash_msg("can't access tty; job control turned off");
3619                                 mflag = on = 0;
3620                                 goto close;
3621                         }
3622                         if (pgrp == getpgrp())
3623                                 break;
3624                         killpg(0, SIGTTIN);
3625                 } while (1);
3626                 initialpgrp = pgrp;
3627
3628                 setsignal(SIGTSTP);
3629                 setsignal(SIGTTOU);
3630                 setsignal(SIGTTIN);
3631                 pgrp = rootpid;
3632                 setpgid(0, pgrp);
3633                 xtcsetpgrp(fd, pgrp);
3634         } else {
3635                 /* turning job control off */
3636                 fd = ttyfd;
3637                 pgrp = initialpgrp;
3638                 /* was xtcsetpgrp, but this can make exiting ash
3639                  * loop forever if pty is already deleted */
3640                 tcsetpgrp(fd, pgrp);
3641                 setpgid(0, pgrp);
3642                 setsignal(SIGTSTP);
3643                 setsignal(SIGTTOU);
3644                 setsignal(SIGTTIN);
3645  close:
3646                 if (fd >= 0)
3647                         close(fd);
3648                 fd = -1;
3649         }
3650         ttyfd = fd;
3651         doing_jobctl = on;
3652 }
3653
3654 static int
3655 killcmd(int argc, char **argv)
3656 {
3657         int i = 1;
3658         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3659                 do {
3660                         if (argv[i][0] == '%') {
3661                                 struct job *jp = getjob(argv[i], 0);
3662                                 unsigned pid = jp->ps[0].pid;
3663                                 /* Enough space for ' -NNN<nul>' */
3664                                 argv[i] = alloca(sizeof(int)*3 + 3);
3665                                 /* kill_main has matching code to expect
3666                                  * leading space. Needed to not confuse
3667                                  * negative pids with "kill -SIGNAL_NO" syntax */
3668                                 sprintf(argv[i], " -%u", pid);
3669                         }
3670                 } while (argv[++i]);
3671         }
3672         return kill_main(argc, argv);
3673 }
3674
3675 static void
3676 showpipe(struct job *jp, FILE *out)
3677 {
3678         struct procstat *sp;
3679         struct procstat *spend;
3680
3681         spend = jp->ps + jp->nprocs;
3682         for (sp = jp->ps + 1; sp < spend; sp++)
3683                 fprintf(out, " | %s", sp->cmd);
3684         outcslow('\n', out);
3685         flush_stdout_stderr();
3686 }
3687
3688
3689 static int
3690 restartjob(struct job *jp, int mode)
3691 {
3692         struct procstat *ps;
3693         int i;
3694         int status;
3695         pid_t pgid;
3696
3697         INT_OFF;
3698         if (jp->state == JOBDONE)
3699                 goto out;
3700         jp->state = JOBRUNNING;
3701         pgid = jp->ps->pid;
3702         if (mode == FORK_FG)
3703                 xtcsetpgrp(ttyfd, pgid);
3704         killpg(pgid, SIGCONT);
3705         ps = jp->ps;
3706         i = jp->nprocs;
3707         do {
3708                 if (WIFSTOPPED(ps->status)) {
3709                         ps->status = -1;
3710                 }
3711                 ps++;
3712         } while (--i);
3713  out:
3714         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3715         INT_ON;
3716         return status;
3717 }
3718
3719 static int
3720 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3721 {
3722         struct job *jp;
3723         FILE *out;
3724         int mode;
3725         int retval;
3726
3727         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3728         nextopt(nullstr);
3729         argv = argptr;
3730         out = stdout;
3731         do {
3732                 jp = getjob(*argv, 1);
3733                 if (mode == FORK_BG) {
3734                         set_curjob(jp, CUR_RUNNING);
3735                         fprintf(out, "[%d] ", jobno(jp));
3736                 }
3737                 outstr(jp->ps->cmd, out);
3738                 showpipe(jp, out);
3739                 retval = restartjob(jp, mode);
3740         } while (*argv && *++argv);
3741         return retval;
3742 }
3743 #endif
3744
3745 static int
3746 sprint_status(char *s, int status, int sigonly)
3747 {
3748         int col;
3749         int st;
3750
3751         col = 0;
3752         if (!WIFEXITED(status)) {
3753 #if JOBS
3754                 if (WIFSTOPPED(status))
3755                         st = WSTOPSIG(status);
3756                 else
3757 #endif
3758                         st = WTERMSIG(status);
3759                 if (sigonly) {
3760                         if (st == SIGINT || st == SIGPIPE)
3761                                 goto out;
3762 #if JOBS
3763                         if (WIFSTOPPED(status))
3764                                 goto out;
3765 #endif
3766                 }
3767                 st &= 0x7f;
3768                 col = fmtstr(s, 32, strsignal(st));
3769                 if (WCOREDUMP(status)) {
3770                         col += fmtstr(s + col, 16, " (core dumped)");
3771                 }
3772         } else if (!sigonly) {
3773                 st = WEXITSTATUS(status);
3774                 if (st)
3775                         col = fmtstr(s, 16, "Done(%d)", st);
3776                 else
3777                         col = fmtstr(s, 16, "Done");
3778         }
3779  out:
3780         return col;
3781 }
3782
3783 static int
3784 dowait(int wait_flags, struct job *job)
3785 {
3786         int pid;
3787         int status;
3788         struct job *jp;
3789         struct job *thisjob;
3790         int state;
3791
3792         TRACE(("dowait(0x%x) called\n", wait_flags));
3793
3794         /* Do a wait system call. If job control is compiled in, we accept
3795          * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3796          * NB: _not_ safe_waitpid, we need to detect EINTR */
3797         pid = waitpid(-1, &status,
3798                         (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3799         TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
3800         if (pid <= 0)
3801                 return pid;
3802
3803         INT_OFF;
3804         thisjob = NULL;
3805         for (jp = curjob; jp; jp = jp->prev_job) {
3806                 struct procstat *sp;
3807                 struct procstat *spend;
3808                 if (jp->state == JOBDONE)
3809                         continue;
3810                 state = JOBDONE;
3811                 spend = jp->ps + jp->nprocs;
3812                 sp = jp->ps;
3813                 do {
3814                         if (sp->pid == pid) {
3815                                 TRACE(("Job %d: changing status of proc %d "
3816                                         "from 0x%x to 0x%x\n",
3817                                         jobno(jp), pid, sp->status, status));
3818                                 sp->status = status;
3819                                 thisjob = jp;
3820                         }
3821                         if (sp->status == -1)
3822                                 state = JOBRUNNING;
3823 #if JOBS
3824                         if (state == JOBRUNNING)
3825                                 continue;
3826                         if (WIFSTOPPED(sp->status)) {
3827                                 jp->stopstatus = sp->status;
3828                                 state = JOBSTOPPED;
3829                         }
3830 #endif
3831                 } while (++sp < spend);
3832                 if (thisjob)
3833                         goto gotjob;
3834         }
3835 #if JOBS
3836         if (!WIFSTOPPED(status))
3837 #endif
3838                 jobless--;
3839         goto out;
3840
3841  gotjob:
3842         if (state != JOBRUNNING) {
3843                 thisjob->changed = 1;
3844
3845                 if (thisjob->state != state) {
3846                         TRACE(("Job %d: changing state from %d to %d\n",
3847                                 jobno(thisjob), thisjob->state, state));
3848                         thisjob->state = state;
3849 #if JOBS
3850                         if (state == JOBSTOPPED) {
3851                                 set_curjob(thisjob, CUR_STOPPED);
3852                         }
3853 #endif
3854                 }
3855         }
3856
3857  out:
3858         INT_ON;
3859
3860         if (thisjob && thisjob == job) {
3861                 char s[48 + 1];
3862                 int len;
3863
3864                 len = sprint_status(s, status, 1);
3865                 if (len) {
3866                         s[len] = '\n';
3867                         s[len + 1] = '\0';
3868                         out2str(s);
3869                 }
3870         }
3871         return pid;
3872 }
3873
3874 static int
3875 blocking_wait_with_raise_on_sig(struct job *job)
3876 {
3877         pid_t pid = dowait(DOWAIT_BLOCK, job);
3878         if (pid <= 0 && pendingsig)
3879                 raise_exception(EXSIG);
3880         return pid;
3881 }
3882
3883 #if JOBS
3884 static void
3885 showjob(FILE *out, struct job *jp, int mode)
3886 {
3887         struct procstat *ps;
3888         struct procstat *psend;
3889         int col;
3890         int indent_col;
3891         char s[80];
3892
3893         ps = jp->ps;
3894
3895         if (mode & SHOW_PGID) {
3896                 /* just output process (group) id of pipeline */
3897                 fprintf(out, "%d\n", ps->pid);
3898                 return;
3899         }
3900
3901         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
3902         indent_col = col;
3903
3904         if (jp == curjob)
3905                 s[col - 2] = '+';
3906         else if (curjob && jp == curjob->prev_job)
3907                 s[col - 2] = '-';
3908
3909         if (mode & SHOW_PID)
3910                 col += fmtstr(s + col, 16, "%d ", ps->pid);
3911
3912         psend = ps + jp->nprocs;
3913
3914         if (jp->state == JOBRUNNING) {
3915                 strcpy(s + col, "Running");
3916                 col += sizeof("Running") - 1;
3917         } else {
3918                 int status = psend[-1].status;
3919                 if (jp->state == JOBSTOPPED)
3920                         status = jp->stopstatus;
3921                 col += sprint_status(s + col, status, 0);
3922         }
3923
3924         goto start;
3925
3926         do {
3927                 /* for each process */
3928                 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3929  start:
3930                 fprintf(out, "%s%*c%s",
3931                         s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3932                 );
3933                 if (!(mode & SHOW_PID)) {
3934                         showpipe(jp, out);
3935                         break;
3936                 }
3937                 if (++ps == psend) {
3938                         outcslow('\n', out);
3939                         break;
3940                 }
3941         } while (1);
3942
3943         jp->changed = 0;
3944
3945         if (jp->state == JOBDONE) {
3946                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3947                 freejob(jp);
3948         }
3949 }
3950
3951 /*
3952  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
3953  * statuses have changed since the last call to showjobs.
3954  */
3955 static void
3956 showjobs(FILE *out, int mode)
3957 {
3958         struct job *jp;
3959
3960         TRACE(("showjobs(%x) called\n", mode));
3961
3962         /* Handle all finished jobs */
3963         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3964                 continue;
3965
3966         for (jp = curjob; jp; jp = jp->prev_job) {
3967                 if (!(mode & SHOW_CHANGED) || jp->changed) {
3968                         showjob(out, jp, mode);
3969                 }
3970         }
3971 }
3972
3973 static int
3974 jobscmd(int argc UNUSED_PARAM, char **argv)
3975 {
3976         int mode, m;
3977
3978         mode = 0;
3979         while ((m = nextopt("lp"))) {
3980                 if (m == 'l')
3981                         mode = SHOW_PID;
3982                 else
3983                         mode = SHOW_PGID;
3984         }
3985
3986         argv = argptr;
3987         if (*argv) {
3988                 do
3989                         showjob(stdout, getjob(*argv,0), mode);
3990                 while (*++argv);
3991         } else
3992                 showjobs(stdout, mode);
3993
3994         return 0;
3995 }
3996 #endif /* JOBS */
3997
3998 static int
3999 getstatus(struct job *job)
4000 {
4001         int status;
4002         int retval;
4003
4004         status = job->ps[job->nprocs - 1].status;
4005         retval = WEXITSTATUS(status);
4006         if (!WIFEXITED(status)) {
4007 #if JOBS
4008                 retval = WSTOPSIG(status);
4009                 if (!WIFSTOPPED(status))
4010 #endif
4011                 {
4012                         /* XXX: limits number of signals */
4013                         retval = WTERMSIG(status);
4014 #if JOBS
4015                         if (retval == SIGINT)
4016                                 job->sigint = 1;
4017 #endif
4018                 }
4019                 retval += 128;
4020         }
4021         TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4022                 jobno(job), job->nprocs, status, retval));
4023         return retval;
4024 }
4025
4026 static int
4027 waitcmd(int argc UNUSED_PARAM, char **argv)
4028 {
4029         struct job *job;
4030         int retval;
4031         struct job *jp;
4032
4033 //      exsig++;
4034 //      xbarrier();
4035         if (pendingsig)
4036                 raise_exception(EXSIG);
4037
4038         nextopt(nullstr);
4039         retval = 0;
4040
4041         argv = argptr;
4042         if (!*argv) {
4043                 /* wait for all jobs */
4044                 for (;;) {
4045                         jp = curjob;
4046                         while (1) {
4047                                 if (!jp) /* no running procs */
4048                                         goto ret;
4049                                 if (jp->state == JOBRUNNING)
4050                                         break;
4051                                 jp->waited = 1;
4052                                 jp = jp->prev_job;
4053                         }
4054         /* man bash:
4055          * "When bash is waiting for an asynchronous command via
4056          * the wait builtin, the reception of a signal for which a trap
4057          * has been set will cause the wait builtin to return immediately
4058          * with an exit status greater than 128, immediately after which
4059          * the trap is executed."
4060          * Do we do it that way? */
4061                         blocking_wait_with_raise_on_sig(NULL);
4062                 }
4063         }
4064
4065         retval = 127;
4066         do {
4067                 if (**argv != '%') {
4068                         pid_t pid = number(*argv);
4069                         job = curjob;
4070                         while (1) {
4071                                 if (!job)
4072                                         goto repeat;
4073                                 if (job->ps[job->nprocs - 1].pid == pid)
4074                                         break;
4075                                 job = job->prev_job;
4076                         }
4077                 } else
4078                         job = getjob(*argv, 0);
4079                 /* loop until process terminated or stopped */
4080                 while (job->state == JOBRUNNING)
4081                         blocking_wait_with_raise_on_sig(NULL);
4082                 job->waited = 1;
4083                 retval = getstatus(job);
4084  repeat: ;
4085         } while (*++argv);
4086
4087  ret:
4088         return retval;
4089 }
4090
4091 static struct job *
4092 growjobtab(void)
4093 {
4094         size_t len;
4095         ptrdiff_t offset;
4096         struct job *jp, *jq;
4097
4098         len = njobs * sizeof(*jp);
4099         jq = jobtab;
4100         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4101
4102         offset = (char *)jp - (char *)jq;
4103         if (offset) {
4104                 /* Relocate pointers */
4105                 size_t l = len;
4106
4107                 jq = (struct job *)((char *)jq + l);
4108                 while (l) {
4109                         l -= sizeof(*jp);
4110                         jq--;
4111 #define joff(p) ((struct job *)((char *)(p) + l))
4112 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4113                         if (joff(jp)->ps == &jq->ps0)
4114                                 jmove(joff(jp)->ps);
4115                         if (joff(jp)->prev_job)
4116                                 jmove(joff(jp)->prev_job);
4117                 }
4118                 if (curjob)
4119                         jmove(curjob);
4120 #undef joff
4121 #undef jmove
4122         }
4123
4124         njobs += 4;
4125         jobtab = jp;
4126         jp = (struct job *)((char *)jp + len);
4127         jq = jp + 3;
4128         do {
4129                 jq->used = 0;
4130         } while (--jq >= jp);
4131         return jp;
4132 }
4133
4134 /*
4135  * Return a new job structure.
4136  * Called with interrupts off.
4137  */
4138 static struct job *
4139 makejob(/*union node *node,*/ int nprocs)
4140 {
4141         int i;
4142         struct job *jp;
4143
4144         for (i = njobs, jp = jobtab; ; jp++) {
4145                 if (--i < 0) {
4146                         jp = growjobtab();
4147                         break;
4148                 }
4149                 if (jp->used == 0)
4150                         break;
4151                 if (jp->state != JOBDONE || !jp->waited)
4152                         continue;
4153 #if JOBS
4154                 if (doing_jobctl)
4155                         continue;
4156 #endif
4157                 freejob(jp);
4158                 break;
4159         }
4160         memset(jp, 0, sizeof(*jp));
4161 #if JOBS
4162         /* jp->jobctl is a bitfield.
4163          * "jp->jobctl |= jobctl" likely to give awful code */
4164         if (doing_jobctl)
4165                 jp->jobctl = 1;
4166 #endif
4167         jp->prev_job = curjob;
4168         curjob = jp;
4169         jp->used = 1;
4170         jp->ps = &jp->ps0;
4171         if (nprocs > 1) {
4172                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4173         }
4174         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4175                                 jobno(jp)));
4176         return jp;
4177 }
4178
4179 #if JOBS
4180 /*
4181  * Return a string identifying a command (to be printed by the
4182  * jobs command).
4183  */
4184 static char *cmdnextc;
4185
4186 static void
4187 cmdputs(const char *s)
4188 {
4189         static const char vstype[VSTYPE + 1][3] = {
4190                 "", "}", "-", "+", "?", "=",
4191                 "%", "%%", "#", "##"
4192                 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4193         };
4194
4195         const char *p, *str;
4196         char c, cc[2] = " ";
4197         char *nextc;
4198         int subtype = 0;
4199         int quoted = 0;
4200
4201         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4202         p = s;
4203         while ((c = *p++) != 0) {
4204                 str = NULL;
4205                 switch (c) {
4206                 case CTLESC:
4207                         c = *p++;
4208                         break;
4209                 case CTLVAR:
4210                         subtype = *p++;
4211                         if ((subtype & VSTYPE) == VSLENGTH)
4212                                 str = "${#";
4213                         else
4214                                 str = "${";
4215                         if (!(subtype & VSQUOTE) == !(quoted & 1))
4216                                 goto dostr;
4217                         quoted ^= 1;
4218                         c = '"';
4219                         break;
4220                 case CTLENDVAR:
4221                         str = "\"}" + !(quoted & 1);
4222                         quoted >>= 1;
4223                         subtype = 0;
4224                         goto dostr;
4225                 case CTLBACKQ:
4226                         str = "$(...)";
4227                         goto dostr;
4228                 case CTLBACKQ+CTLQUOTE:
4229                         str = "\"$(...)\"";
4230                         goto dostr;
4231 #if ENABLE_ASH_MATH_SUPPORT
4232                 case CTLARI:
4233                         str = "$((";
4234                         goto dostr;
4235                 case CTLENDARI:
4236                         str = "))";
4237                         goto dostr;
4238 #endif
4239                 case CTLQUOTEMARK:
4240                         quoted ^= 1;
4241                         c = '"';
4242                         break;
4243                 case '=':
4244                         if (subtype == 0)
4245                                 break;
4246                         if ((subtype & VSTYPE) != VSNORMAL)
4247                                 quoted <<= 1;
4248                         str = vstype[subtype & VSTYPE];
4249                         if (subtype & VSNUL)
4250                                 c = ':';
4251                         else
4252                                 goto checkstr;
4253                         break;
4254                 case '\'':
4255                 case '\\':
4256                 case '"':
4257                 case '$':
4258                         /* These can only happen inside quotes */
4259                         cc[0] = c;
4260                         str = cc;
4261                         c = '\\';
4262                         break;
4263                 default:
4264                         break;
4265                 }
4266                 USTPUTC(c, nextc);
4267  checkstr:
4268                 if (!str)
4269                         continue;
4270  dostr:
4271                 while ((c = *str++)) {
4272                         USTPUTC(c, nextc);
4273                 }
4274         }
4275         if (quoted & 1) {
4276                 USTPUTC('"', nextc);
4277         }
4278         *nextc = 0;
4279         cmdnextc = nextc;
4280 }
4281
4282 /* cmdtxt() and cmdlist() call each other */
4283 static void cmdtxt(union node *n);
4284
4285 static void
4286 cmdlist(union node *np, int sep)
4287 {
4288         for (; np; np = np->narg.next) {
4289                 if (!sep)
4290                         cmdputs(" ");
4291                 cmdtxt(np);
4292                 if (sep && np->narg.next)
4293                         cmdputs(" ");
4294         }
4295 }
4296
4297 static void
4298 cmdtxt(union node *n)
4299 {
4300         union node *np;
4301         struct nodelist *lp;
4302         const char *p;
4303
4304         if (!n)
4305                 return;
4306         switch (n->type) {
4307         default:
4308 #if DEBUG
4309                 abort();
4310 #endif
4311         case NPIPE:
4312                 lp = n->npipe.cmdlist;
4313                 for (;;) {
4314                         cmdtxt(lp->n);
4315                         lp = lp->next;
4316                         if (!lp)
4317                                 break;
4318                         cmdputs(" | ");
4319                 }
4320                 break;
4321         case NSEMI:
4322                 p = "; ";
4323                 goto binop;
4324         case NAND:
4325                 p = " && ";
4326                 goto binop;
4327         case NOR:
4328                 p = " || ";
4329  binop:
4330                 cmdtxt(n->nbinary.ch1);
4331                 cmdputs(p);
4332                 n = n->nbinary.ch2;
4333                 goto donode;
4334         case NREDIR:
4335         case NBACKGND:
4336                 n = n->nredir.n;
4337                 goto donode;
4338         case NNOT:
4339                 cmdputs("!");
4340                 n = n->nnot.com;
4341  donode:
4342                 cmdtxt(n);
4343                 break;
4344         case NIF:
4345                 cmdputs("if ");
4346                 cmdtxt(n->nif.test);
4347                 cmdputs("; then ");
4348                 n = n->nif.ifpart;
4349                 if (n->nif.elsepart) {
4350                         cmdtxt(n);
4351                         cmdputs("; else ");
4352                         n = n->nif.elsepart;
4353                 }
4354                 p = "; fi";
4355                 goto dotail;
4356         case NSUBSHELL:
4357                 cmdputs("(");
4358                 n = n->nredir.n;
4359                 p = ")";
4360                 goto dotail;
4361         case NWHILE:
4362                 p = "while ";
4363                 goto until;
4364         case NUNTIL:
4365                 p = "until ";
4366  until:
4367                 cmdputs(p);
4368                 cmdtxt(n->nbinary.ch1);
4369                 n = n->nbinary.ch2;
4370                 p = "; done";
4371  dodo:
4372                 cmdputs("; do ");
4373  dotail:
4374                 cmdtxt(n);
4375                 goto dotail2;
4376         case NFOR:
4377                 cmdputs("for ");
4378                 cmdputs(n->nfor.var);
4379                 cmdputs(" in ");
4380                 cmdlist(n->nfor.args, 1);
4381                 n = n->nfor.body;
4382                 p = "; done";
4383                 goto dodo;
4384         case NDEFUN:
4385                 cmdputs(n->narg.text);
4386                 p = "() { ... }";
4387                 goto dotail2;
4388         case NCMD:
4389                 cmdlist(n->ncmd.args, 1);
4390                 cmdlist(n->ncmd.redirect, 0);
4391                 break;
4392         case NARG:
4393                 p = n->narg.text;
4394  dotail2:
4395                 cmdputs(p);
4396                 break;
4397         case NHERE:
4398         case NXHERE:
4399                 p = "<<...";
4400                 goto dotail2;
4401         case NCASE:
4402                 cmdputs("case ");
4403                 cmdputs(n->ncase.expr->narg.text);
4404                 cmdputs(" in ");
4405                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4406                         cmdtxt(np->nclist.pattern);
4407                         cmdputs(") ");
4408                         cmdtxt(np->nclist.body);
4409                         cmdputs(";; ");
4410                 }
4411                 p = "esac";
4412                 goto dotail2;
4413         case NTO:
4414                 p = ">";
4415                 goto redir;
4416         case NCLOBBER:
4417                 p = ">|";
4418                 goto redir;
4419         case NAPPEND:
4420                 p = ">>";
4421                 goto redir;
4422 #if ENABLE_ASH_BASH_COMPAT
4423         case NTO2:
4424 #endif
4425         case NTOFD:
4426                 p = ">&";
4427                 goto redir;
4428         case NFROM:
4429                 p = "<";
4430                 goto redir;
4431         case NFROMFD:
4432                 p = "<&";
4433                 goto redir;
4434         case NFROMTO:
4435                 p = "<>";
4436  redir:
4437                 cmdputs(utoa(n->nfile.fd));
4438                 cmdputs(p);
4439                 if (n->type == NTOFD || n->type == NFROMFD) {
4440                         cmdputs(utoa(n->ndup.dupfd));
4441                         break;
4442                 }
4443                 n = n->nfile.fname;
4444                 goto donode;
4445         }
4446 }
4447
4448 static char *
4449 commandtext(union node *n)
4450 {
4451         char *name;
4452
4453         STARTSTACKSTR(cmdnextc);
4454         cmdtxt(n);
4455         name = stackblock();
4456         TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4457                         name, cmdnextc, cmdnextc));
4458         return ckstrdup(name);
4459 }
4460 #endif /* JOBS */
4461
4462 /*
4463  * Fork off a subshell.  If we are doing job control, give the subshell its
4464  * own process group.  Jp is a job structure that the job is to be added to.
4465  * N is the command that will be evaluated by the child.  Both jp and n may
4466  * be NULL.  The mode parameter can be one of the following:
4467  *      FORK_FG - Fork off a foreground process.
4468  *      FORK_BG - Fork off a background process.
4469  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4470  *                   process group even if job control is on.
4471  *
4472  * When job control is turned off, background processes have their standard
4473  * input redirected to /dev/null (except for the second and later processes
4474  * in a pipeline).
4475  *
4476  * Called with interrupts off.
4477  */
4478 /*
4479  * Clear traps on a fork.
4480  */
4481 static void
4482 clear_traps(void)
4483 {
4484         char **tp;
4485
4486         for (tp = trap; tp < &trap[NSIG]; tp++) {
4487                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4488                         INT_OFF;
4489                         free(*tp);
4490                         *tp = NULL;
4491                         if (tp != &trap[0])
4492                                 setsignal(tp - trap);
4493                         INT_ON;
4494                 }
4495         }
4496 }
4497
4498 /* Lives far away from here, needed for forkchild */
4499 static void closescript(void);
4500
4501 /* Called after fork(), in child */
4502 static void
4503 forkchild(struct job *jp, /*union node *n,*/ int mode)
4504 {
4505         int oldlvl;
4506
4507         TRACE(("Child shell %d\n", getpid()));
4508         oldlvl = shlvl;
4509         shlvl++;
4510
4511         /* man bash: "Non-builtin commands run by bash have signal handlers
4512          * set to the values inherited by the shell from its parent".
4513          * Do we do it correctly? */
4514
4515         closescript();
4516         clear_traps();
4517 #if JOBS
4518         /* do job control only in root shell */
4519         doing_jobctl = 0;
4520         if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4521                 pid_t pgrp;
4522
4523                 if (jp->nprocs == 0)
4524                         pgrp = getpid();
4525                 else
4526                         pgrp = jp->ps[0].pid;
4527                 /* this can fail because we are doing it in the parent also */
4528                 setpgid(0, pgrp);
4529                 if (mode == FORK_FG)
4530                         xtcsetpgrp(ttyfd, pgrp);
4531                 setsignal(SIGTSTP);
4532                 setsignal(SIGTTOU);
4533         } else
4534 #endif
4535         if (mode == FORK_BG) {
4536                 /* man bash: "When job control is not in effect,
4537                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4538                 ignoresig(SIGINT);
4539                 ignoresig(SIGQUIT);
4540                 if (jp->nprocs == 0) {
4541                         close(0);
4542                         if (open(bb_dev_null, O_RDONLY) != 0)
4543                                 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4544                 }
4545         }
4546         if (!oldlvl) {
4547                 if (iflag) { /* why if iflag only? */
4548                         setsignal(SIGINT);
4549                         setsignal(SIGTERM);
4550                 }
4551                 /* man bash:
4552                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4553                  * commands run by bash have signal handlers
4554                  * set to the values inherited by the shell
4555                  * from its parent".
4556                  * Take care of the second rule: */
4557                 setsignal(SIGQUIT);
4558         }
4559         for (jp = curjob; jp; jp = jp->prev_job)
4560                 freejob(jp);
4561         jobless = 0;
4562 }
4563
4564 /* Called after fork(), in parent */
4565 #if !JOBS
4566 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4567 #endif
4568 static void
4569 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4570 {
4571         TRACE(("In parent shell: child = %d\n", pid));
4572         if (!jp) {
4573                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4574                         continue;
4575                 jobless++;
4576                 return;
4577         }
4578 #if JOBS
4579         if (mode != FORK_NOJOB && jp->jobctl) {
4580                 int pgrp;
4581
4582                 if (jp->nprocs == 0)
4583                         pgrp = pid;
4584                 else
4585                         pgrp = jp->ps[0].pid;
4586                 /* This can fail because we are doing it in the child also */
4587                 setpgid(pid, pgrp);
4588         }
4589 #endif
4590         if (mode == FORK_BG) {
4591                 backgndpid = pid;               /* set $! */
4592                 set_curjob(jp, CUR_RUNNING);
4593         }
4594         if (jp) {
4595                 struct procstat *ps = &jp->ps[jp->nprocs++];
4596                 ps->pid = pid;
4597                 ps->status = -1;
4598                 ps->cmd = nullstr;
4599 #if JOBS
4600                 if (doing_jobctl && n)
4601                         ps->cmd = commandtext(n);
4602 #endif
4603         }
4604 }
4605
4606 static int
4607 forkshell(struct job *jp, union node *n, int mode)
4608 {
4609         int pid;
4610
4611         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4612         pid = fork();
4613         if (pid < 0) {
4614                 TRACE(("Fork failed, errno=%d", errno));
4615                 if (jp)
4616                         freejob(jp);
4617                 ash_msg_and_raise_error("can't fork");
4618         }
4619         if (pid == 0)
4620                 forkchild(jp, /*n,*/ mode);
4621         else
4622                 forkparent(jp, n, mode, pid);
4623         return pid;
4624 }
4625
4626 /*
4627  * Wait for job to finish.
4628  *
4629  * Under job control we have the problem that while a child process
4630  * is running interrupts generated by the user are sent to the child
4631  * but not to the shell.  This means that an infinite loop started by
4632  * an interactive user may be hard to kill.  With job control turned off,
4633  * an interactive user may place an interactive program inside a loop.
4634  * If the interactive program catches interrupts, the user doesn't want
4635  * these interrupts to also abort the loop.  The approach we take here
4636  * is to have the shell ignore interrupt signals while waiting for a
4637  * foreground process to terminate, and then send itself an interrupt
4638  * signal if the child process was terminated by an interrupt signal.
4639  * Unfortunately, some programs want to do a bit of cleanup and then
4640  * exit on interrupt; unless these processes terminate themselves by
4641  * sending a signal to themselves (instead of calling exit) they will
4642  * confuse this approach.
4643  *
4644  * Called with interrupts off.
4645  */
4646 static int
4647 waitforjob(struct job *jp)
4648 {
4649         int st;
4650
4651         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4652
4653         INT_OFF;
4654         while (jp->state == JOBRUNNING) {
4655                 /* In non-interactive shells, we _can_ get
4656                  * a keyboard signal here and be EINTRed,
4657                  * but we just loop back, waiting for command to complete.
4658                  *
4659                  * man bash:
4660                  * "If bash is waiting for a command to complete and receives
4661                  * a signal for which a trap has been set, the trap
4662                  * will not be executed until the command completes."
4663                  *
4664                  * Reality is that even if trap is not set, bash
4665                  * will not act on the signal until command completes.
4666                  * Try this. sleep5intoff.c:
4667                  * #include <signal.h>
4668                  * #include <unistd.h>
4669                  * int main() {
4670                  *         sigset_t set;
4671                  *         sigemptyset(&set);
4672                  *         sigaddset(&set, SIGINT);
4673                  *         sigaddset(&set, SIGQUIT);
4674                  *         sigprocmask(SIG_BLOCK, &set, NULL);
4675                  *         sleep(5);
4676                  *         return 0;
4677                  * }
4678                  * $ bash -c './sleep5intoff; echo hi'
4679                  * ^C^C^C^C <--- pressing ^C once a second
4680                  * $ _
4681                  * $ bash -c './sleep5intoff; echo hi'
4682                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4683                  * $ _
4684                  */
4685                 dowait(DOWAIT_BLOCK, jp);
4686         }
4687         INT_ON;
4688
4689         st = getstatus(jp);
4690 #if JOBS
4691         if (jp->jobctl) {
4692                 xtcsetpgrp(ttyfd, rootpid);
4693                 /*
4694                  * This is truly gross.
4695                  * If we're doing job control, then we did a TIOCSPGRP which
4696                  * caused us (the shell) to no longer be in the controlling
4697                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
4698                  * intuit from the subprocess exit status whether a SIGINT
4699                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
4700                  */
4701                 if (jp->sigint) /* TODO: do the same with all signals */
4702                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
4703         }
4704         if (jp->state == JOBDONE)
4705 #endif
4706                 freejob(jp);
4707         return st;
4708 }
4709
4710 /*
4711  * return 1 if there are stopped jobs, otherwise 0
4712  */
4713 static int
4714 stoppedjobs(void)
4715 {
4716         struct job *jp;
4717         int retval;
4718
4719         retval = 0;
4720         if (job_warning)
4721                 goto out;
4722         jp = curjob;
4723         if (jp && jp->state == JOBSTOPPED) {
4724                 out2str("You have stopped jobs.\n");
4725                 job_warning = 2;
4726                 retval++;
4727         }
4728  out:
4729         return retval;
4730 }
4731
4732
4733 /* ============ redir.c
4734  *
4735  * Code for dealing with input/output redirection.
4736  */
4737
4738 #define EMPTY -2                /* marks an unused slot in redirtab */
4739 #define CLOSED -3               /* marks a slot of previously-closed fd */
4740
4741 /*
4742  * Open a file in noclobber mode.
4743  * The code was copied from bash.
4744  */
4745 static int
4746 noclobberopen(const char *fname)
4747 {
4748         int r, fd;
4749         struct stat finfo, finfo2;
4750
4751         /*
4752          * If the file exists and is a regular file, return an error
4753          * immediately.
4754          */
4755         r = stat(fname, &finfo);
4756         if (r == 0 && S_ISREG(finfo.st_mode)) {
4757                 errno = EEXIST;
4758                 return -1;
4759         }
4760
4761         /*
4762          * If the file was not present (r != 0), make sure we open it
4763          * exclusively so that if it is created before we open it, our open
4764          * will fail.  Make sure that we do not truncate an existing file.
4765          * Note that we don't turn on O_EXCL unless the stat failed -- if the
4766          * file was not a regular file, we leave O_EXCL off.
4767          */
4768         if (r != 0)
4769                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4770         fd = open(fname, O_WRONLY|O_CREAT, 0666);
4771
4772         /* If the open failed, return the file descriptor right away. */
4773         if (fd < 0)
4774                 return fd;
4775
4776         /*
4777          * OK, the open succeeded, but the file may have been changed from a
4778          * non-regular file to a regular file between the stat and the open.
4779          * We are assuming that the O_EXCL open handles the case where FILENAME
4780          * did not exist and is symlinked to an existing file between the stat
4781          * and open.
4782          */
4783
4784         /*
4785          * If we can open it and fstat the file descriptor, and neither check
4786          * revealed that it was a regular file, and the file has not been
4787          * replaced, return the file descriptor.
4788          */
4789         if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4790          && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4791                 return fd;
4792
4793         /* The file has been replaced.  badness. */
4794         close(fd);
4795         errno = EEXIST;
4796         return -1;
4797 }
4798
4799 /*
4800  * Handle here documents.  Normally we fork off a process to write the
4801  * data to a pipe.  If the document is short, we can stuff the data in
4802  * the pipe without forking.
4803  */
4804 /* openhere needs this forward reference */
4805 static void expandhere(union node *arg, int fd);
4806 static int
4807 openhere(union node *redir)
4808 {
4809         int pip[2];
4810         size_t len = 0;
4811
4812         if (pipe(pip) < 0)
4813                 ash_msg_and_raise_error("pipe call failed");
4814         if (redir->type == NHERE) {
4815                 len = strlen(redir->nhere.doc->narg.text);
4816                 if (len <= PIPE_BUF) {
4817                         full_write(pip[1], redir->nhere.doc->narg.text, len);
4818                         goto out;
4819                 }
4820         }
4821         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4822                 /* child */
4823                 close(pip[0]);
4824                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
4825                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4826                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
4827                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4828                 signal(SIGPIPE, SIG_DFL);
4829                 if (redir->type == NHERE)
4830                         full_write(pip[1], redir->nhere.doc->narg.text, len);
4831                 else /* NXHERE */
4832                         expandhere(redir->nhere.doc, pip[1]);
4833                 _exit(EXIT_SUCCESS);
4834         }
4835  out:
4836         close(pip[1]);
4837         return pip[0];
4838 }
4839
4840 static int
4841 openredirect(union node *redir)
4842 {
4843         char *fname;
4844         int f;
4845
4846         switch (redir->nfile.type) {
4847         case NFROM:
4848                 fname = redir->nfile.expfname;
4849                 f = open(fname, O_RDONLY);
4850                 if (f < 0)
4851                         goto eopen;
4852                 break;
4853         case NFROMTO:
4854                 fname = redir->nfile.expfname;
4855                 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4856                 if (f < 0)
4857                         goto ecreate;
4858                 break;
4859         case NTO:
4860 #if ENABLE_ASH_BASH_COMPAT
4861         case NTO2:
4862 #endif
4863                 /* Take care of noclobber mode. */
4864                 if (Cflag) {
4865                         fname = redir->nfile.expfname;
4866                         f = noclobberopen(fname);
4867                         if (f < 0)
4868                                 goto ecreate;
4869                         break;
4870                 }
4871                 /* FALLTHROUGH */
4872         case NCLOBBER:
4873                 fname = redir->nfile.expfname;
4874                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4875                 if (f < 0)
4876                         goto ecreate;
4877                 break;
4878         case NAPPEND:
4879                 fname = redir->nfile.expfname;
4880                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4881                 if (f < 0)
4882                         goto ecreate;
4883                 break;
4884         default:
4885 #if DEBUG
4886                 abort();
4887 #endif
4888                 /* Fall through to eliminate warning. */
4889 /* Our single caller does this itself */
4890 //      case NTOFD:
4891 //      case NFROMFD:
4892 //              f = -1;
4893 //              break;
4894         case NHERE:
4895         case NXHERE:
4896                 f = openhere(redir);
4897                 break;
4898         }
4899
4900         return f;
4901  ecreate:
4902         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4903  eopen:
4904         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4905 }
4906
4907 /*
4908  * Copy a file descriptor to be >= to.  Returns -1
4909  * if the source file descriptor is closed, EMPTY if there are no unused
4910  * file descriptors left.
4911  */
4912 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4913  * old code was doing close(to) prior to copyfd() to achieve the same */
4914 enum {
4915         COPYFD_EXACT   = (int)~(INT_MAX),
4916         COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4917 };
4918 static int
4919 copyfd(int from, int to)
4920 {
4921         int newfd;
4922
4923         if (to & COPYFD_EXACT) {
4924                 to &= ~COPYFD_EXACT;
4925                 /*if (from != to)*/
4926                         newfd = dup2(from, to);
4927         } else {
4928                 newfd = fcntl(from, F_DUPFD, to);
4929         }
4930         if (newfd < 0) {
4931                 if (errno == EMFILE)
4932                         return EMPTY;
4933                 /* Happens when source fd is not open: try "echo >&99" */
4934                 ash_msg_and_raise_error("%d: %m", from);
4935         }
4936         return newfd;
4937 }
4938
4939 /* Struct def and variable are moved down to the first usage site */
4940 struct two_fd_t {
4941         int orig, copy;
4942 };
4943 struct redirtab {
4944         struct redirtab *next;
4945         int nullredirs;
4946         int pair_count;
4947         struct two_fd_t two_fd[0];
4948 };
4949 #define redirlist (G_var.redirlist)
4950
4951 static int need_to_remember(struct redirtab *rp, int fd)
4952 {
4953         int i;
4954
4955         if (!rp) /* remembering was not requested */
4956                 return 0;
4957
4958         for (i = 0; i < rp->pair_count; i++) {
4959                 if (rp->two_fd[i].orig == fd) {
4960                         /* already remembered */
4961                         return 0;
4962                 }
4963         }
4964         return 1;
4965 }
4966
4967 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4968 static int is_hidden_fd(struct redirtab *rp, int fd)
4969 {
4970         int i;
4971         struct parsefile *pf;
4972
4973         if (fd == -1)
4974                 return 0;
4975         pf = g_parsefile;
4976         while (pf) {
4977                 if (fd == pf->fd) {
4978                         return 1;
4979                 }
4980                 pf = pf->prev;
4981         }
4982         if (!rp)
4983                 return 0;
4984         fd |= COPYFD_RESTORE;
4985         for (i = 0; i < rp->pair_count; i++) {
4986                 if (rp->two_fd[i].copy == fd) {
4987                         return 1;
4988                 }
4989         }
4990         return 0;
4991 }
4992
4993 /*
4994  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
4995  * old file descriptors are stashed away so that the redirection can be
4996  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
4997  * standard output, and the standard error if it becomes a duplicate of
4998  * stdout, is saved in memory.
4999  */
5000 /* flags passed to redirect */
5001 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5002 #define REDIR_SAVEFD2 03        /* set preverrout */
5003 static void
5004 redirect(union node *redir, int flags)
5005 {
5006         struct redirtab *sv;
5007         int sv_pos;
5008         int i;
5009         int fd;
5010         int newfd;
5011         int copied_fd2 = -1;
5012
5013         g_nullredirs++;
5014         if (!redir) {
5015                 return;
5016         }
5017
5018         sv = NULL;
5019         sv_pos = 0;
5020         INT_OFF;
5021         if (flags & REDIR_PUSH) {
5022                 union node *tmp = redir;
5023                 do {
5024                         sv_pos++;
5025 #if ENABLE_ASH_BASH_COMPAT
5026                         if (redir->nfile.type == NTO2)
5027                                 sv_pos++;
5028 #endif
5029                         tmp = tmp->nfile.next;
5030                 } while (tmp);
5031                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5032                 sv->next = redirlist;
5033                 sv->pair_count = sv_pos;
5034                 redirlist = sv;
5035                 sv->nullredirs = g_nullredirs - 1;
5036                 g_nullredirs = 0;
5037                 while (sv_pos > 0) {
5038                         sv_pos--;
5039                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5040                 }
5041         }
5042
5043         do {
5044                 fd = redir->nfile.fd;
5045                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5046                         int right_fd = redir->ndup.dupfd;
5047                         /* redirect from/to same file descriptor? */
5048                         if (right_fd == fd)
5049                                 continue;
5050                         /* echo >&10 and 10 is a fd opened to the sh script? */
5051                         if (is_hidden_fd(sv, right_fd)) {
5052                                 errno = EBADF; /* as if it is closed */
5053                                 ash_msg_and_raise_error("%d: %m", right_fd);
5054                         }
5055                         newfd = -1;
5056                 } else {
5057                         newfd = openredirect(redir); /* always >= 0 */
5058                         if (fd == newfd) {
5059                                 /* Descriptor wasn't open before redirect.
5060                                  * Mark it for close in the future */
5061                                 if (need_to_remember(sv, fd)) {
5062                                         goto remember_to_close;
5063                                 }
5064                                 continue;
5065                         }
5066                 }
5067 #if ENABLE_ASH_BASH_COMPAT
5068  redirect_more:
5069 #endif
5070                 if (need_to_remember(sv, fd)) {
5071                         /* Copy old descriptor */
5072                         i = fcntl(fd, F_DUPFD, 10);
5073 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5074  * are closed in popredir() in the child, preventing them from leaking
5075  * into child. (popredir() also cleans up the mess in case of failures)
5076  */
5077                         if (i == -1) {
5078                                 i = errno;
5079                                 if (i != EBADF) {
5080                                         /* Strange error (e.g. "too many files" EMFILE?) */
5081                                         if (newfd >= 0)
5082                                                 close(newfd);
5083                                         errno = i;
5084                                         ash_msg_and_raise_error("%d: %m", fd);
5085                                         /* NOTREACHED */
5086                                 }
5087                                 /* EBADF: it is not open - good, remember to close it */
5088  remember_to_close:
5089                                 i = CLOSED;
5090                         } else { /* fd is open, save its copy */
5091                                 /* "exec fd>&-" should not close fds
5092                                  * which point to script file(s).
5093                                  * Force them to be restored afterwards */
5094                                 if (is_hidden_fd(sv, fd))
5095                                         i |= COPYFD_RESTORE;
5096                         }
5097                         if (fd == 2)
5098                                 copied_fd2 = i;
5099                         sv->two_fd[sv_pos].orig = fd;
5100                         sv->two_fd[sv_pos].copy = i;
5101                         sv_pos++;
5102                 }
5103                 if (newfd < 0) {
5104                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5105                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5106                                 close(fd);
5107                         } else {
5108                                 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5109                         }
5110                 } else if (fd != newfd) { /* move newfd to fd */
5111                         copyfd(newfd, fd | COPYFD_EXACT);
5112 #if ENABLE_ASH_BASH_COMPAT
5113                         if (!(redir->nfile.type == NTO2 && fd == 2))
5114 #endif
5115                                 close(newfd);
5116                 }
5117 #if ENABLE_ASH_BASH_COMPAT
5118                 if (redir->nfile.type == NTO2 && fd == 1) {
5119                         /* We already redirected it to fd 1, now copy it to 2 */
5120                         newfd = 1;
5121                         fd = 2;
5122                         goto redirect_more;
5123                 }
5124 #endif
5125         } while ((redir = redir->nfile.next) != NULL);
5126
5127         INT_ON;
5128         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5129                 preverrout_fd = copied_fd2;
5130 }
5131
5132 /*
5133  * Undo the effects of the last redirection.
5134  */
5135 static void
5136 popredir(int drop, int restore)
5137 {
5138         struct redirtab *rp;
5139         int i;
5140
5141         if (--g_nullredirs >= 0)
5142                 return;
5143         INT_OFF;
5144         rp = redirlist;
5145         for (i = 0; i < rp->pair_count; i++) {
5146                 int fd = rp->two_fd[i].orig;
5147                 int copy = rp->two_fd[i].copy;
5148                 if (copy == CLOSED) {
5149                         if (!drop)
5150                                 close(fd);
5151                         continue;
5152                 }
5153                 if (copy != EMPTY) {
5154                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5155                                 copy &= ~COPYFD_RESTORE;
5156                                 /*close(fd);*/
5157                                 copyfd(copy, fd | COPYFD_EXACT);
5158                         }
5159                         close(copy);
5160                 }
5161         }
5162         redirlist = rp->next;
5163         g_nullredirs = rp->nullredirs;
5164         free(rp);
5165         INT_ON;
5166 }
5167
5168 /*
5169  * Undo all redirections.  Called on error or interrupt.
5170  */
5171
5172 /*
5173  * Discard all saved file descriptors.
5174  */
5175 static void
5176 clearredir(int drop)
5177 {
5178         for (;;) {
5179                 g_nullredirs = 0;
5180                 if (!redirlist)
5181                         break;
5182                 popredir(drop, /*restore:*/ 0);
5183         }
5184 }
5185
5186 static int
5187 redirectsafe(union node *redir, int flags)
5188 {
5189         int err;
5190         volatile int saveint;
5191         struct jmploc *volatile savehandler = exception_handler;
5192         struct jmploc jmploc;
5193
5194         SAVE_INT(saveint);
5195         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5196         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5197         if (!err) {
5198                 exception_handler = &jmploc;
5199                 redirect(redir, flags);
5200         }
5201         exception_handler = savehandler;
5202         if (err && exception != EXERROR)
5203                 longjmp(exception_handler->loc, 1);
5204         RESTORE_INT(saveint);
5205         return err;
5206 }
5207
5208
5209 /* ============ Routines to expand arguments to commands
5210  *
5211  * We have to deal with backquotes, shell variables, and file metacharacters.
5212  */
5213
5214 #if ENABLE_ASH_MATH_SUPPORT_64
5215 typedef int64_t arith_t;
5216 #define arith_t_type long long
5217 #else
5218 typedef long arith_t;
5219 #define arith_t_type long
5220 #endif
5221
5222 #if ENABLE_ASH_MATH_SUPPORT
5223 static arith_t dash_arith(const char *);
5224 static arith_t arith(const char *expr, int *perrcode);
5225 #endif
5226
5227 /*
5228  * expandarg flags
5229  */
5230 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5231 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5232 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5233 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5234 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5235 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
5236 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5237 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5238 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
5239 /*
5240  * _rmescape() flags
5241  */
5242 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5243 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5244 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
5245 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5246 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5247
5248 /*
5249  * Structure specifying which parts of the string should be searched
5250  * for IFS characters.
5251  */
5252 struct ifsregion {
5253         struct ifsregion *next; /* next region in list */
5254         int begoff;             /* offset of start of region */
5255         int endoff;             /* offset of end of region */
5256         int nulonly;            /* search for nul bytes only */
5257 };
5258
5259 struct arglist {
5260         struct strlist *list;
5261         struct strlist **lastp;
5262 };
5263
5264 /* output of current string */
5265 static char *expdest;
5266 /* list of back quote expressions */
5267 static struct nodelist *argbackq;
5268 /* first struct in list of ifs regions */
5269 static struct ifsregion ifsfirst;
5270 /* last struct in list */
5271 static struct ifsregion *ifslastp;
5272 /* holds expanded arg list */
5273 static struct arglist exparg;
5274
5275 /*
5276  * Our own itoa().
5277  */
5278 static int
5279 cvtnum(arith_t num)
5280 {
5281         int len;
5282
5283         expdest = makestrspace(32, expdest);
5284 #if ENABLE_ASH_MATH_SUPPORT_64
5285         len = fmtstr(expdest, 32, "%lld", (long long) num);
5286 #else
5287         len = fmtstr(expdest, 32, "%ld", num);
5288 #endif
5289         STADJUST(len, expdest);
5290         return len;
5291 }
5292
5293 static size_t
5294 esclen(const char *start, const char *p)
5295 {
5296         size_t esc = 0;
5297
5298         while (p > start && *--p == CTLESC) {
5299                 esc++;
5300         }
5301         return esc;
5302 }
5303
5304 /*
5305  * Remove any CTLESC characters from a string.
5306  */
5307 static char *
5308 _rmescapes(char *str, int flag)
5309 {
5310         static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5311
5312         char *p, *q, *r;
5313         unsigned inquotes;
5314         int notescaped;
5315         int globbing;
5316
5317         p = strpbrk(str, qchars);
5318         if (!p) {
5319                 return str;
5320         }
5321         q = p;
5322         r = str;
5323         if (flag & RMESCAPE_ALLOC) {
5324                 size_t len = p - str;
5325                 size_t fulllen = len + strlen(p) + 1;
5326
5327                 if (flag & RMESCAPE_GROW) {
5328                         r = makestrspace(fulllen, expdest);
5329                 } else if (flag & RMESCAPE_HEAP) {
5330                         r = ckmalloc(fulllen);
5331                 } else {
5332                         r = stalloc(fulllen);
5333                 }
5334                 q = r;
5335                 if (len > 0) {
5336                         q = (char *)memcpy(q, str, len) + len;
5337                 }
5338         }
5339         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5340         globbing = flag & RMESCAPE_GLOB;
5341         notescaped = globbing;
5342         while (*p) {
5343                 if (*p == CTLQUOTEMARK) {
5344                         inquotes = ~inquotes;
5345                         p++;
5346                         notescaped = globbing;
5347                         continue;
5348                 }
5349                 if (*p == '\\') {
5350                         /* naked back slash */
5351                         notescaped = 0;
5352                         goto copy;
5353                 }
5354                 if (*p == CTLESC) {
5355                         p++;
5356                         if (notescaped && inquotes && *p != '/') {
5357                                 *q++ = '\\';
5358                         }
5359                 }
5360                 notescaped = globbing;
5361  copy:
5362                 *q++ = *p++;
5363         }
5364         *q = '\0';
5365         if (flag & RMESCAPE_GROW) {
5366                 expdest = r;
5367                 STADJUST(q - r + 1, expdest);
5368         }
5369         return r;
5370 }
5371 #define rmescapes(p) _rmescapes((p), 0)
5372
5373 #define pmatch(a, b) !fnmatch((a), (b), 0)
5374
5375 /*
5376  * Prepare a pattern for a expmeta (internal glob(3)) call.
5377  *
5378  * Returns an stalloced string.
5379  */
5380 static char *
5381 preglob(const char *pattern, int quoted, int flag)
5382 {
5383         flag |= RMESCAPE_GLOB;
5384         if (quoted) {
5385                 flag |= RMESCAPE_QUOTED;
5386         }
5387         return _rmescapes((char *)pattern, flag);
5388 }
5389
5390 /*
5391  * Put a string on the stack.
5392  */
5393 static void
5394 memtodest(const char *p, size_t len, int syntax, int quotes)
5395 {
5396         char *q = expdest;
5397
5398         q = makestrspace(len * 2, q);
5399
5400         while (len--) {
5401                 int c = signed_char2int(*p++);
5402                 if (!c)
5403                         continue;
5404                 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5405                         USTPUTC(CTLESC, q);
5406                 USTPUTC(c, q);
5407         }
5408
5409         expdest = q;
5410 }
5411
5412 static void
5413 strtodest(const char *p, int syntax, int quotes)
5414 {
5415         memtodest(p, strlen(p), syntax, quotes);
5416 }
5417
5418 /*
5419  * Record the fact that we have to scan this region of the
5420  * string for IFS characters.
5421  */
5422 static void
5423 recordregion(int start, int end, int nulonly)
5424 {
5425         struct ifsregion *ifsp;
5426
5427         if (ifslastp == NULL) {
5428                 ifsp = &ifsfirst;
5429         } else {
5430                 INT_OFF;
5431                 ifsp = ckzalloc(sizeof(*ifsp));
5432                 /*ifsp->next = NULL; - ckzalloc did it */
5433                 ifslastp->next = ifsp;
5434                 INT_ON;
5435         }
5436         ifslastp = ifsp;
5437         ifslastp->begoff = start;
5438         ifslastp->endoff = end;
5439         ifslastp->nulonly = nulonly;
5440 }
5441
5442 static void
5443 removerecordregions(int endoff)
5444 {
5445         if (ifslastp == NULL)
5446                 return;
5447
5448         if (ifsfirst.endoff > endoff) {
5449                 while (ifsfirst.next != NULL) {
5450                         struct ifsregion *ifsp;
5451                         INT_OFF;
5452                         ifsp = ifsfirst.next->next;
5453                         free(ifsfirst.next);
5454                         ifsfirst.next = ifsp;
5455                         INT_ON;
5456                 }
5457                 if (ifsfirst.begoff > endoff)
5458                         ifslastp = NULL;
5459                 else {
5460                         ifslastp = &ifsfirst;
5461                         ifsfirst.endoff = endoff;
5462                 }
5463                 return;
5464         }
5465
5466         ifslastp = &ifsfirst;
5467         while (ifslastp->next && ifslastp->next->begoff < endoff)
5468                 ifslastp=ifslastp->next;
5469         while (ifslastp->next != NULL) {
5470                 struct ifsregion *ifsp;
5471                 INT_OFF;
5472                 ifsp = ifslastp->next->next;
5473                 free(ifslastp->next);
5474                 ifslastp->next = ifsp;
5475                 INT_ON;
5476         }
5477         if (ifslastp->endoff > endoff)
5478                 ifslastp->endoff = endoff;
5479 }
5480
5481 static char *
5482 exptilde(char *startp, char *p, int flag)
5483 {
5484         char c;
5485         char *name;
5486         struct passwd *pw;
5487         const char *home;
5488         int quotes = flag & (EXP_FULL | EXP_CASE);
5489         int startloc;
5490
5491         name = p + 1;
5492
5493         while ((c = *++p) != '\0') {
5494                 switch (c) {
5495                 case CTLESC:
5496                         return startp;
5497                 case CTLQUOTEMARK:
5498                         return startp;
5499                 case ':':
5500                         if (flag & EXP_VARTILDE)
5501                                 goto done;
5502                         break;
5503                 case '/':
5504                 case CTLENDVAR:
5505                         goto done;
5506                 }
5507         }
5508  done:
5509         *p = '\0';
5510         if (*name == '\0') {
5511                 home = lookupvar(homestr);
5512         } else {
5513                 pw = getpwnam(name);
5514                 if (pw == NULL)
5515                         goto lose;
5516                 home = pw->pw_dir;
5517         }
5518         if (!home || !*home)
5519                 goto lose;
5520         *p = c;
5521         startloc = expdest - (char *)stackblock();
5522         strtodest(home, SQSYNTAX, quotes);
5523         recordregion(startloc, expdest - (char *)stackblock(), 0);
5524         return p;
5525  lose:
5526         *p = c;
5527         return startp;
5528 }
5529
5530 /*
5531  * Execute a command inside back quotes.  If it's a builtin command, we
5532  * want to save its output in a block obtained from malloc.  Otherwise
5533  * we fork off a subprocess and get the output of the command via a pipe.
5534  * Should be called with interrupts off.
5535  */
5536 struct backcmd {                /* result of evalbackcmd */
5537         int fd;                 /* file descriptor to read from */
5538         int nleft;              /* number of chars in buffer */
5539         char *buf;              /* buffer */
5540         struct job *jp;         /* job structure for command */
5541 };
5542
5543 /* These forward decls are needed to use "eval" code for backticks handling: */
5544 static uint8_t back_exitstatus; /* exit status of backquoted command */
5545 #define EV_EXIT 01              /* exit after evaluating tree */
5546 static void evaltree(union node *, int);
5547
5548 static void
5549 evalbackcmd(union node *n, struct backcmd *result)
5550 {
5551         int saveherefd;
5552
5553         result->fd = -1;
5554         result->buf = NULL;
5555         result->nleft = 0;
5556         result->jp = NULL;
5557         if (n == NULL)
5558                 goto out;
5559
5560         saveherefd = herefd;
5561         herefd = -1;
5562
5563         {
5564                 int pip[2];
5565                 struct job *jp;
5566
5567                 if (pipe(pip) < 0)
5568                         ash_msg_and_raise_error("pipe call failed");
5569                 jp = makejob(/*n,*/ 1);
5570                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5571                         FORCE_INT_ON;
5572                         close(pip[0]);
5573                         if (pip[1] != 1) {
5574                                 /*close(1);*/
5575                                 copyfd(pip[1], 1 | COPYFD_EXACT);
5576                                 close(pip[1]);
5577                         }
5578                         eflag = 0;
5579                         evaltree(n, EV_EXIT); /* actually evaltreenr... */
5580                         /* NOTREACHED */
5581                 }
5582                 close(pip[1]);
5583                 result->fd = pip[0];
5584                 result->jp = jp;
5585         }
5586         herefd = saveherefd;
5587  out:
5588         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5589                 result->fd, result->buf, result->nleft, result->jp));
5590 }
5591
5592 /*
5593  * Expand stuff in backwards quotes.
5594  */
5595 static void
5596 expbackq(union node *cmd, int quoted, int quotes)
5597 {
5598         struct backcmd in;
5599         int i;
5600         char buf[128];
5601         char *p;
5602         char *dest;
5603         int startloc;
5604         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5605         struct stackmark smark;
5606
5607         INT_OFF;
5608         setstackmark(&smark);
5609         dest = expdest;
5610         startloc = dest - (char *)stackblock();
5611         grabstackstr(dest);
5612         evalbackcmd(cmd, &in);
5613         popstackmark(&smark);
5614
5615         p = in.buf;
5616         i = in.nleft;
5617         if (i == 0)
5618                 goto read;
5619         for (;;) {
5620                 memtodest(p, i, syntax, quotes);
5621  read:
5622                 if (in.fd < 0)
5623                         break;
5624                 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5625                 TRACE(("expbackq: read returns %d\n", i));
5626                 if (i <= 0)
5627                         break;
5628                 p = buf;
5629         }
5630
5631         free(in.buf);
5632         if (in.fd >= 0) {
5633                 close(in.fd);
5634                 back_exitstatus = waitforjob(in.jp);
5635         }
5636         INT_ON;
5637
5638         /* Eat all trailing newlines */
5639         dest = expdest;
5640         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5641                 STUNPUTC(dest);
5642         expdest = dest;
5643
5644         if (quoted == 0)
5645                 recordregion(startloc, dest - (char *)stackblock(), 0);
5646         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5647                 (dest - (char *)stackblock()) - startloc,
5648                 (dest - (char *)stackblock()) - startloc,
5649                 stackblock() + startloc));
5650 }
5651
5652 #if ENABLE_ASH_MATH_SUPPORT
5653 /*
5654  * Expand arithmetic expression.  Backup to start of expression,
5655  * evaluate, place result in (backed up) result, adjust string position.
5656  */
5657 static void
5658 expari(int quotes)
5659 {
5660         char *p, *start;
5661         int begoff;
5662         int flag;
5663         int len;
5664
5665         /* ifsfree(); */
5666
5667         /*
5668          * This routine is slightly over-complicated for
5669          * efficiency.  Next we scan backwards looking for the
5670          * start of arithmetic.
5671          */
5672         start = stackblock();
5673         p = expdest - 1;
5674         *p = '\0';
5675         p--;
5676         do {
5677                 int esc;
5678
5679                 while (*p != CTLARI) {
5680                         p--;
5681 #if DEBUG
5682                         if (p < start) {
5683                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5684                         }
5685 #endif
5686                 }
5687
5688                 esc = esclen(start, p);
5689                 if (!(esc % 2)) {
5690                         break;
5691                 }
5692
5693                 p -= esc + 1;
5694         } while (1);
5695
5696         begoff = p - start;
5697
5698         removerecordregions(begoff);
5699
5700         flag = p[1];
5701
5702         expdest = p;
5703
5704         if (quotes)
5705                 rmescapes(p + 2);
5706
5707         len = cvtnum(dash_arith(p + 2));
5708
5709         if (flag != '"')
5710                 recordregion(begoff, begoff + len, 0);
5711 }
5712 #endif
5713
5714 /* argstr needs it */
5715 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5716
5717 /*
5718  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
5719  * characters to allow for further processing.  Otherwise treat
5720  * $@ like $* since no splitting will be performed.
5721  *
5722  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5723  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5724  * for correct expansion of "B=$A" word.
5725  */
5726 static void
5727 argstr(char *p, int flag, struct strlist *var_str_list)
5728 {
5729         static const char spclchars[] ALIGN1 = {
5730                 '=',
5731                 ':',
5732                 CTLQUOTEMARK,
5733                 CTLENDVAR,
5734                 CTLESC,
5735                 CTLVAR,
5736                 CTLBACKQ,
5737                 CTLBACKQ | CTLQUOTE,
5738 #if ENABLE_ASH_MATH_SUPPORT
5739                 CTLENDARI,
5740 #endif
5741                 0
5742         };
5743         const char *reject = spclchars;
5744         int c;
5745         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
5746         int breakall = flag & EXP_WORD;
5747         int inquotes;
5748         size_t length;
5749         int startloc;
5750
5751         if (!(flag & EXP_VARTILDE)) {
5752                 reject += 2;
5753         } else if (flag & EXP_VARTILDE2) {
5754                 reject++;
5755         }
5756         inquotes = 0;
5757         length = 0;
5758         if (flag & EXP_TILDE) {
5759                 char *q;
5760
5761                 flag &= ~EXP_TILDE;
5762  tilde:
5763                 q = p;
5764                 if (*q == CTLESC && (flag & EXP_QWORD))
5765                         q++;
5766                 if (*q == '~')
5767                         p = exptilde(p, q, flag);
5768         }
5769  start:
5770         startloc = expdest - (char *)stackblock();
5771         for (;;) {
5772                 length += strcspn(p + length, reject);
5773                 c = p[length];
5774                 if (c && (!(c & 0x80)
5775 #if ENABLE_ASH_MATH_SUPPORT
5776                                         || c == CTLENDARI
5777 #endif
5778                    )) {
5779                         /* c == '=' || c == ':' || c == CTLENDARI */
5780                         length++;
5781                 }
5782                 if (length > 0) {
5783                         int newloc;
5784                         expdest = stack_nputstr(p, length, expdest);
5785                         newloc = expdest - (char *)stackblock();
5786                         if (breakall && !inquotes && newloc > startloc) {
5787                                 recordregion(startloc, newloc, 0);
5788                         }
5789                         startloc = newloc;
5790                 }
5791                 p += length + 1;
5792                 length = 0;
5793
5794                 switch (c) {
5795                 case '\0':
5796                         goto breakloop;
5797                 case '=':
5798                         if (flag & EXP_VARTILDE2) {
5799                                 p--;
5800                                 continue;
5801                         }
5802                         flag |= EXP_VARTILDE2;
5803                         reject++;
5804                         /* fall through */
5805                 case ':':
5806                         /*
5807                          * sort of a hack - expand tildes in variable
5808                          * assignments (after the first '=' and after ':'s).
5809                          */
5810                         if (*--p == '~') {
5811                                 goto tilde;
5812                         }
5813                         continue;
5814                 }
5815
5816                 switch (c) {
5817                 case CTLENDVAR: /* ??? */
5818                         goto breakloop;
5819                 case CTLQUOTEMARK:
5820                         /* "$@" syntax adherence hack */
5821                         if (
5822                                 !inquotes &&
5823                                 !memcmp(p, dolatstr, 4) &&
5824                                 (p[4] == CTLQUOTEMARK || (
5825                                         p[4] == CTLENDVAR &&
5826                                         p[5] == CTLQUOTEMARK
5827                                 ))
5828                         ) {
5829                                 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5830                                 goto start;
5831                         }
5832                         inquotes = !inquotes;
5833  addquote:
5834                         if (quotes) {
5835                                 p--;
5836                                 length++;
5837                                 startloc++;
5838                         }
5839                         break;
5840                 case CTLESC:
5841                         startloc++;
5842                         length++;
5843                         goto addquote;
5844                 case CTLVAR:
5845                         p = evalvar(p, flag, var_str_list);
5846                         goto start;
5847                 case CTLBACKQ:
5848                         c = 0;
5849                 case CTLBACKQ|CTLQUOTE:
5850                         expbackq(argbackq->n, c, quotes);
5851                         argbackq = argbackq->next;
5852                         goto start;
5853 #if ENABLE_ASH_MATH_SUPPORT
5854                 case CTLENDARI:
5855                         p--;
5856                         expari(quotes);
5857                         goto start;
5858 #endif
5859                 }
5860         }
5861  breakloop:
5862         ;
5863 }
5864
5865 static char *
5866 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5867         int zero)
5868 {
5869 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5870 // as part of a larger change when he added support for ${var/a/b}.
5871 // However, it broke # and % operators:
5872 //
5873 //var=ababcdcd
5874 //                 ok       bad
5875 //echo ${var#ab}   abcdcd   abcdcd
5876 //echo ${var##ab}  abcdcd   abcdcd
5877 //echo ${var#a*b}  abcdcd   ababcdcd  (!)
5878 //echo ${var##a*b} cdcd     cdcd
5879 //echo ${var#?}    babcdcd  ababcdcd  (!)
5880 //echo ${var##?}   babcdcd  babcdcd
5881 //echo ${var#*}    ababcdcd babcdcd   (!)
5882 //echo ${var##*}
5883 //echo ${var%cd}   ababcd   ababcd
5884 //echo ${var%%cd}  ababcd   abab      (!)
5885 //echo ${var%c*d}  ababcd   ababcd
5886 //echo ${var%%c*d} abab     ababcdcd  (!)
5887 //echo ${var%?}    ababcdc  ababcdc
5888 //echo ${var%%?}   ababcdc  ababcdcd  (!)
5889 //echo ${var%*}    ababcdcd ababcdcd
5890 //echo ${var%%*}
5891 //
5892 // Commenting it back out helped. Remove it completely if it really
5893 // is not needed.
5894
5895         char *loc, *loc2; //, *full;
5896         char c;
5897
5898         loc = startp;
5899         loc2 = rmesc;
5900         do {
5901                 int match; // = strlen(str);
5902                 const char *s = loc2;
5903
5904                 c = *loc2;
5905                 if (zero) {
5906                         *loc2 = '\0';
5907                         s = rmesc;
5908                 }
5909                 match = pmatch(str, s); // this line was deleted
5910
5911 //              // chop off end if its '*'
5912 //              full = strrchr(str, '*');
5913 //              if (full && full != str)
5914 //                      match--;
5915 //
5916 //              // If str starts with '*' replace with s.
5917 //              if ((*str == '*') && strlen(s) >= match) {
5918 //                      full = xstrdup(s);
5919 //                      strncpy(full+strlen(s)-match+1, str+1, match-1);
5920 //              } else
5921 //                      full = xstrndup(str, match);
5922 //              match = strncmp(s, full, strlen(full));
5923 //              free(full);
5924 //
5925                 *loc2 = c;
5926                 if (match) // if (!match)
5927                         return loc;
5928                 if (quotes && *loc == CTLESC)
5929                         loc++;
5930                 loc++;
5931                 loc2++;
5932         } while (c);
5933         return 0;
5934 }
5935
5936 static char *
5937 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5938         int zero)
5939 {
5940         int esc = 0;
5941         char *loc;
5942         char *loc2;
5943
5944         for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5945                 int match;
5946                 char c = *loc2;
5947                 const char *s = loc2;
5948                 if (zero) {
5949                         *loc2 = '\0';
5950                         s = rmesc;
5951                 }
5952                 match = pmatch(str, s);
5953                 *loc2 = c;
5954                 if (match)
5955                         return loc;
5956                 loc--;
5957                 if (quotes) {
5958                         if (--esc < 0) {
5959                                 esc = esclen(startp, loc);
5960                         }
5961                         if (esc % 2) {
5962                                 esc--;
5963                                 loc--;
5964                         }
5965                 }
5966         }
5967         return 0;
5968 }
5969
5970 static void varunset(const char *, const char *, const char *, int) NORETURN;
5971 static void
5972 varunset(const char *end, const char *var, const char *umsg, int varflags)
5973 {
5974         const char *msg;
5975         const char *tail;
5976
5977         tail = nullstr;
5978         msg = "parameter not set";
5979         if (umsg) {
5980                 if (*end == CTLENDVAR) {
5981                         if (varflags & VSNUL)
5982                                 tail = " or null";
5983                 } else {
5984                         msg = umsg;
5985                 }
5986         }
5987         ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5988 }
5989
5990 #if ENABLE_ASH_BASH_COMPAT
5991 static char *
5992 parse_sub_pattern(char *arg, int inquotes)
5993 {
5994         char *idx, *repl = NULL;
5995         unsigned char c;
5996
5997         idx = arg;
5998         while (1) {
5999                 c = *arg;
6000                 if (!c)
6001                         break;
6002                 if (c == '/') {
6003                         /* Only the first '/' seen is our separator */
6004                         if (!repl) {
6005                                 repl = idx + 1;
6006                                 c = '\0';
6007                         }
6008                 }
6009                 *idx++ = c;
6010                 if (!inquotes && c == '\\' && arg[1] == '\\')
6011                         arg++; /* skip both \\, not just first one */
6012                 arg++;
6013         }
6014         *idx = c; /* NUL */
6015
6016         return repl;
6017 }
6018 #endif /* ENABLE_ASH_BASH_COMPAT */
6019
6020 static const char *
6021 subevalvar(char *p, char *str, int strloc, int subtype,
6022                 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6023 {
6024         struct nodelist *saveargbackq = argbackq;
6025         char *startp;
6026         char *loc;
6027         char *rmesc, *rmescend;
6028         USE_ASH_BASH_COMPAT(char *repl = NULL;)
6029         USE_ASH_BASH_COMPAT(char null = '\0';)
6030         USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6031         int saveherefd = herefd;
6032         int amount, workloc, resetloc;
6033         int zero;
6034         char *(*scan)(char*, char*, char*, char*, int, int);
6035
6036         herefd = -1;
6037         argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6038                         var_str_list);
6039         STPUTC('\0', expdest);
6040         herefd = saveherefd;
6041         argbackq = saveargbackq;
6042         startp = (char *)stackblock() + startloc;
6043
6044         switch (subtype) {
6045         case VSASSIGN:
6046                 setvar(str, startp, 0);
6047                 amount = startp - expdest;
6048                 STADJUST(amount, expdest);
6049                 return startp;
6050
6051 #if ENABLE_ASH_BASH_COMPAT
6052         case VSSUBSTR:
6053                 loc = str = stackblock() + strloc;
6054 // TODO: number() instead? It does error checking...
6055                 pos = atoi(loc);
6056                 len = str - startp - 1;
6057
6058                 /* *loc != '\0', guaranteed by parser */
6059                 if (quotes) {
6060                         char *ptr;
6061
6062                         /* We must adjust the length by the number of escapes we find. */
6063                         for (ptr = startp; ptr < (str - 1); ptr++) {
6064                                 if (*ptr == CTLESC) {
6065                                         len--;
6066                                         ptr++;
6067                                 }
6068                         }
6069                 }
6070                 orig_len = len;
6071
6072                 if (*loc++ == ':') {
6073 // TODO: number() instead? It does error checking...
6074                         len = atoi(loc);
6075                 } else {
6076                         len = orig_len;
6077                         while (*loc && *loc != ':')
6078                                 loc++;
6079                         if (*loc++ == ':')
6080 // TODO: number() instead? It does error checking...
6081                                 len = atoi(loc);
6082                 }
6083                 if (pos >= orig_len) {
6084                         pos = 0;
6085                         len = 0;
6086                 }
6087                 if (len > (orig_len - pos))
6088                         len = orig_len - pos;
6089
6090                 for (str = startp; pos; str++, pos--) {
6091                         if (quotes && *str == CTLESC)
6092                                 str++;
6093                 }
6094                 for (loc = startp; len; len--) {
6095                         if (quotes && *str == CTLESC)
6096                                 *loc++ = *str++;
6097                         *loc++ = *str++;
6098                 }
6099                 *loc = '\0';
6100                 amount = loc - expdest;
6101                 STADJUST(amount, expdest);
6102                 return loc;
6103 #endif
6104
6105         case VSQUESTION:
6106                 varunset(p, str, startp, varflags);
6107                 /* NOTREACHED */
6108         }
6109         resetloc = expdest - (char *)stackblock();
6110
6111         /* We'll comeback here if we grow the stack while handling
6112          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6113          * stack will need rebasing, and we'll need to remove our work
6114          * areas each time
6115          */
6116  USE_ASH_BASH_COMPAT(restart:)
6117
6118         amount = expdest - ((char *)stackblock() + resetloc);
6119         STADJUST(-amount, expdest);
6120         startp = (char *)stackblock() + startloc;
6121
6122         rmesc = startp;
6123         rmescend = (char *)stackblock() + strloc;
6124         if (quotes) {
6125                 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6126                 if (rmesc != startp) {
6127                         rmescend = expdest;
6128                         startp = (char *)stackblock() + startloc;
6129                 }
6130         }
6131         rmescend--;
6132         str = (char *)stackblock() + strloc;
6133         preglob(str, varflags & VSQUOTE, 0);
6134         workloc = expdest - (char *)stackblock();
6135
6136 #if ENABLE_ASH_BASH_COMPAT
6137         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6138                 char *idx, *end, *restart_detect;
6139
6140                 if (!repl) {
6141                         repl = parse_sub_pattern(str, varflags & VSQUOTE);
6142                         if (!repl)
6143                                 repl = &null;
6144                 }
6145
6146                 /* If there's no pattern to match, return the expansion unmolested */
6147                 if (*str == '\0')
6148                         return 0;
6149
6150                 len = 0;
6151                 idx = startp;
6152                 end = str - 1;
6153                 while (idx < end) {
6154                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6155                         if (!loc) {
6156                                 /* No match, advance */
6157                                 restart_detect = stackblock();
6158                                 STPUTC(*idx, expdest);
6159                                 if (quotes && *idx == CTLESC) {
6160                                         idx++;
6161                                         len++;
6162                                         STPUTC(*idx, expdest);
6163                                 }
6164                                 if (stackblock() != restart_detect)
6165                                         goto restart;
6166                                 idx++;
6167                                 len++;
6168                                 rmesc++;
6169                                 continue;
6170                         }
6171
6172                         if (subtype == VSREPLACEALL) {
6173                                 while (idx < loc) {
6174                                         if (quotes && *idx == CTLESC)
6175                                                 idx++;
6176                                         idx++;
6177                                         rmesc++;
6178                                 }
6179                         } else {
6180                                 idx = loc;
6181                         }
6182
6183                         for (loc = repl; *loc; loc++) {
6184                                 restart_detect = stackblock();
6185                                 STPUTC(*loc, expdest);
6186                                 if (stackblock() != restart_detect)
6187                                         goto restart;
6188                                 len++;
6189                         }
6190
6191                         if (subtype == VSREPLACE) {
6192                                 while (*idx) {
6193                                         restart_detect = stackblock();
6194                                         STPUTC(*idx, expdest);
6195                                         if (stackblock() != restart_detect)
6196                                                 goto restart;
6197                                         len++;
6198                                         idx++;
6199                                 }
6200                                 break;
6201                         }
6202                 }
6203
6204                 /* We've put the replaced text into a buffer at workloc, now
6205                  * move it to the right place and adjust the stack.
6206                  */
6207                 startp = stackblock() + startloc;
6208                 STPUTC('\0', expdest);
6209                 memmove(startp, stackblock() + workloc, len);
6210                 startp[len++] = '\0';
6211                 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6212                 STADJUST(-amount, expdest);
6213                 return startp;
6214         }
6215 #endif /* ENABLE_ASH_BASH_COMPAT */
6216
6217         subtype -= VSTRIMRIGHT;
6218 #if DEBUG
6219         if (subtype < 0 || subtype > 7)
6220                 abort();
6221 #endif
6222         /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6223         zero = subtype >> 1;
6224         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6225         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6226
6227         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6228         if (loc) {
6229                 if (zero) {
6230                         memmove(startp, loc, str - loc);
6231                         loc = startp + (str - loc) - 1;
6232                 }
6233                 *loc = '\0';
6234                 amount = loc - expdest;
6235                 STADJUST(amount, expdest);
6236         }
6237         return loc;
6238 }
6239
6240 /*
6241  * Add the value of a specialized variable to the stack string.
6242  */
6243 static ssize_t
6244 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6245 {
6246         int num;
6247         char *p;
6248         int i;
6249         int sep = 0;
6250         int sepq = 0;
6251         ssize_t len = 0;
6252         char **ap;
6253         int syntax;
6254         int quoted = varflags & VSQUOTE;
6255         int subtype = varflags & VSTYPE;
6256         int quotes = flags & (EXP_FULL | EXP_CASE);
6257
6258         if (quoted && (flags & EXP_FULL))
6259                 sep = 1 << CHAR_BIT;
6260
6261         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6262         switch (*name) {
6263         case '$':
6264                 num = rootpid;
6265                 goto numvar;
6266         case '?':
6267                 num = exitstatus;
6268                 goto numvar;
6269         case '#':
6270                 num = shellparam.nparam;
6271                 goto numvar;
6272         case '!':
6273                 num = backgndpid;
6274                 if (num == 0)
6275                         return -1;
6276  numvar:
6277                 len = cvtnum(num);
6278                 break;
6279         case '-':
6280                 p = makestrspace(NOPTS, expdest);
6281                 for (i = NOPTS - 1; i >= 0; i--) {
6282                         if (optlist[i]) {
6283                                 USTPUTC(optletters(i), p);
6284                                 len++;
6285                         }
6286                 }
6287                 expdest = p;
6288                 break;
6289         case '@':
6290                 if (sep)
6291                         goto param;
6292                 /* fall through */
6293         case '*':
6294                 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6295                 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6296                         sepq = 1;
6297  param:
6298                 ap = shellparam.p;
6299                 if (!ap)
6300                         return -1;
6301                 while ((p = *ap++)) {
6302                         size_t partlen;
6303
6304                         partlen = strlen(p);
6305                         len += partlen;
6306
6307                         if (!(subtype == VSPLUS || subtype == VSLENGTH))
6308                                 memtodest(p, partlen, syntax, quotes);
6309
6310                         if (*ap && sep) {
6311                                 char *q;
6312
6313                                 len++;
6314                                 if (subtype == VSPLUS || subtype == VSLENGTH) {
6315                                         continue;
6316                                 }
6317                                 q = expdest;
6318                                 if (sepq)
6319                                         STPUTC(CTLESC, q);
6320                                 STPUTC(sep, q);
6321                                 expdest = q;
6322                         }
6323                 }
6324                 return len;
6325         case '0':
6326         case '1':
6327         case '2':
6328         case '3':
6329         case '4':
6330         case '5':
6331         case '6':
6332         case '7':
6333         case '8':
6334         case '9':
6335 // TODO: number() instead? It does error checking...
6336                 num = atoi(name);
6337                 if (num < 0 || num > shellparam.nparam)
6338                         return -1;
6339                 p = num ? shellparam.p[num - 1] : arg0;
6340                 goto value;
6341         default:
6342                 /* NB: name has form "VAR=..." */
6343
6344                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6345                  * which should be considered before we check variables. */
6346                 if (var_str_list) {
6347                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6348                         p = NULL;
6349                         do {
6350                                 char *str, *eq;
6351                                 str = var_str_list->text;
6352                                 eq = strchr(str, '=');
6353                                 if (!eq) /* stop at first non-assignment */
6354                                         break;
6355                                 eq++;
6356                                 if (name_len == (unsigned)(eq - str)
6357                                  && strncmp(str, name, name_len) == 0) {
6358                                         p = eq;
6359                                         /* goto value; - WRONG! */
6360                                         /* think "A=1 A=2 B=$A" */
6361                                 }
6362                                 var_str_list = var_str_list->next;
6363                         } while (var_str_list);
6364                         if (p)
6365                                 goto value;
6366                 }
6367                 p = lookupvar(name);
6368  value:
6369                 if (!p)
6370                         return -1;
6371
6372                 len = strlen(p);
6373                 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6374                         memtodest(p, len, syntax, quotes);
6375                 return len;
6376         }
6377
6378         if (subtype == VSPLUS || subtype == VSLENGTH)
6379                 STADJUST(-len, expdest);
6380         return len;
6381 }
6382
6383 /*
6384  * Expand a variable, and return a pointer to the next character in the
6385  * input string.
6386  */
6387 static char *
6388 evalvar(char *p, int flag, struct strlist *var_str_list)
6389 {
6390         char varflags;
6391         char subtype;
6392         char quoted;
6393         char easy;
6394         char *var;
6395         int patloc;
6396         int startloc;
6397         ssize_t varlen;
6398
6399         varflags = *p++;
6400         subtype = varflags & VSTYPE;
6401         quoted = varflags & VSQUOTE;
6402         var = p;
6403         easy = (!quoted || (*var == '@' && shellparam.nparam));
6404         startloc = expdest - (char *)stackblock();
6405         p = strchr(p, '=') + 1;
6406
6407  again:
6408         varlen = varvalue(var, varflags, flag, var_str_list);
6409         if (varflags & VSNUL)
6410                 varlen--;
6411
6412         if (subtype == VSPLUS) {
6413                 varlen = -1 - varlen;
6414                 goto vsplus;
6415         }
6416
6417         if (subtype == VSMINUS) {
6418  vsplus:
6419                 if (varlen < 0) {
6420                         argstr(
6421                                 p, flag | EXP_TILDE |
6422                                         (quoted ?  EXP_QWORD : EXP_WORD),
6423                                 var_str_list
6424                         );
6425                         goto end;
6426                 }
6427                 if (easy)
6428                         goto record;
6429                 goto end;
6430         }
6431
6432         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6433                 if (varlen < 0) {
6434                         if (subevalvar(p, var, /* strloc: */ 0,
6435                                         subtype, startloc, varflags,
6436                                         /* quotes: */ 0,
6437                                         var_str_list)
6438                         ) {
6439                                 varflags &= ~VSNUL;
6440                                 /*
6441                                  * Remove any recorded regions beyond
6442                                  * start of variable
6443                                  */
6444                                 removerecordregions(startloc);
6445                                 goto again;
6446                         }
6447                         goto end;
6448                 }
6449                 if (easy)
6450                         goto record;
6451                 goto end;
6452         }
6453
6454         if (varlen < 0 && uflag)
6455                 varunset(p, var, 0, 0);
6456
6457         if (subtype == VSLENGTH) {
6458                 cvtnum(varlen > 0 ? varlen : 0);
6459                 goto record;
6460         }
6461
6462         if (subtype == VSNORMAL) {
6463                 if (easy)
6464                         goto record;
6465                 goto end;
6466         }
6467
6468 #if DEBUG
6469         switch (subtype) {
6470         case VSTRIMLEFT:
6471         case VSTRIMLEFTMAX:
6472         case VSTRIMRIGHT:
6473         case VSTRIMRIGHTMAX:
6474 #if ENABLE_ASH_BASH_COMPAT
6475         case VSSUBSTR:
6476         case VSREPLACE:
6477         case VSREPLACEALL:
6478 #endif
6479                 break;
6480         default:
6481                 abort();
6482         }
6483 #endif
6484
6485         if (varlen >= 0) {
6486                 /*
6487                  * Terminate the string and start recording the pattern
6488                  * right after it
6489                  */
6490                 STPUTC('\0', expdest);
6491                 patloc = expdest - (char *)stackblock();
6492                 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6493                                 startloc, varflags,
6494                                 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6495                                 var_str_list)
6496                 ) {
6497                         int amount = expdest - (
6498                                 (char *)stackblock() + patloc - 1
6499                         );
6500                         STADJUST(-amount, expdest);
6501                 }
6502                 /* Remove any recorded regions beyond start of variable */
6503                 removerecordregions(startloc);
6504  record:
6505                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6506         }
6507
6508  end:
6509         if (subtype != VSNORMAL) {      /* skip to end of alternative */
6510                 int nesting = 1;
6511                 for (;;) {
6512                         char c = *p++;
6513                         if (c == CTLESC)
6514                                 p++;
6515                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6516                                 if (varlen >= 0)
6517                                         argbackq = argbackq->next;
6518                         } else if (c == CTLVAR) {
6519                                 if ((*p++ & VSTYPE) != VSNORMAL)
6520                                         nesting++;
6521                         } else if (c == CTLENDVAR) {
6522                                 if (--nesting == 0)
6523                                         break;
6524                         }
6525                 }
6526         }
6527         return p;
6528 }
6529
6530 /*
6531  * Break the argument string into pieces based upon IFS and add the
6532  * strings to the argument list.  The regions of the string to be
6533  * searched for IFS characters have been stored by recordregion.
6534  */
6535 static void
6536 ifsbreakup(char *string, struct arglist *arglist)
6537 {
6538         struct ifsregion *ifsp;
6539         struct strlist *sp;
6540         char *start;
6541         char *p;
6542         char *q;
6543         const char *ifs, *realifs;
6544         int ifsspc;
6545         int nulonly;
6546
6547         start = string;
6548         if (ifslastp != NULL) {
6549                 ifsspc = 0;
6550                 nulonly = 0;
6551                 realifs = ifsset() ? ifsval() : defifs;
6552                 ifsp = &ifsfirst;
6553                 do {
6554                         p = string + ifsp->begoff;
6555                         nulonly = ifsp->nulonly;
6556                         ifs = nulonly ? nullstr : realifs;
6557                         ifsspc = 0;
6558                         while (p < string + ifsp->endoff) {
6559                                 q = p;
6560                                 if (*p == CTLESC)
6561                                         p++;
6562                                 if (!strchr(ifs, *p)) {
6563                                         p++;
6564                                         continue;
6565                                 }
6566                                 if (!nulonly)
6567                                         ifsspc = (strchr(defifs, *p) != NULL);
6568                                 /* Ignore IFS whitespace at start */
6569                                 if (q == start && ifsspc) {
6570                                         p++;
6571                                         start = p;
6572                                         continue;
6573                                 }
6574                                 *q = '\0';
6575                                 sp = stzalloc(sizeof(*sp));
6576                                 sp->text = start;
6577                                 *arglist->lastp = sp;
6578                                 arglist->lastp = &sp->next;
6579                                 p++;
6580                                 if (!nulonly) {
6581                                         for (;;) {
6582                                                 if (p >= string + ifsp->endoff) {
6583                                                         break;
6584                                                 }
6585                                                 q = p;
6586                                                 if (*p == CTLESC)
6587                                                         p++;
6588                                                 if (strchr(ifs, *p) == NULL) {
6589                                                         p = q;
6590                                                         break;
6591                                                 }
6592                                                 if (strchr(defifs, *p) == NULL) {
6593                                                         if (ifsspc) {
6594                                                                 p++;
6595                                                                 ifsspc = 0;
6596                                                         } else {
6597                                                                 p = q;
6598                                                                 break;
6599                                                         }
6600                                                 } else
6601                                                         p++;
6602                                         }
6603                                 }
6604                                 start = p;
6605                         } /* while */
6606                         ifsp = ifsp->next;
6607                 } while (ifsp != NULL);
6608                 if (nulonly)
6609                         goto add;
6610         }
6611
6612         if (!*start)
6613                 return;
6614
6615  add:
6616         sp = stzalloc(sizeof(*sp));
6617         sp->text = start;
6618         *arglist->lastp = sp;
6619         arglist->lastp = &sp->next;
6620 }
6621
6622 static void
6623 ifsfree(void)
6624 {
6625         struct ifsregion *p;
6626
6627         INT_OFF;
6628         p = ifsfirst.next;
6629         do {
6630                 struct ifsregion *ifsp;
6631                 ifsp = p->next;
6632                 free(p);
6633                 p = ifsp;
6634         } while (p);
6635         ifslastp = NULL;
6636         ifsfirst.next = NULL;
6637         INT_ON;
6638 }
6639
6640 /*
6641  * Add a file name to the list.
6642  */
6643 static void
6644 addfname(const char *name)
6645 {
6646         struct strlist *sp;
6647
6648         sp = stzalloc(sizeof(*sp));
6649         sp->text = ststrdup(name);
6650         *exparg.lastp = sp;
6651         exparg.lastp = &sp->next;
6652 }
6653
6654 static char *expdir;
6655
6656 /*
6657  * Do metacharacter (i.e. *, ?, [...]) expansion.
6658  */
6659 static void
6660 expmeta(char *enddir, char *name)
6661 {
6662         char *p;
6663         const char *cp;
6664         char *start;
6665         char *endname;
6666         int metaflag;
6667         struct stat statb;
6668         DIR *dirp;
6669         struct dirent *dp;
6670         int atend;
6671         int matchdot;
6672
6673         metaflag = 0;
6674         start = name;
6675         for (p = name; *p; p++) {
6676                 if (*p == '*' || *p == '?')
6677                         metaflag = 1;
6678                 else if (*p == '[') {
6679                         char *q = p + 1;
6680                         if (*q == '!')
6681                                 q++;
6682                         for (;;) {
6683                                 if (*q == '\\')
6684                                         q++;
6685                                 if (*q == '/' || *q == '\0')
6686                                         break;
6687                                 if (*++q == ']') {
6688                                         metaflag = 1;
6689                                         break;
6690                                 }
6691                         }
6692                 } else if (*p == '\\')
6693                         p++;
6694                 else if (*p == '/') {
6695                         if (metaflag)
6696                                 goto out;
6697                         start = p + 1;
6698                 }
6699         }
6700  out:
6701         if (metaflag == 0) {    /* we've reached the end of the file name */
6702                 if (enddir != expdir)
6703                         metaflag++;
6704                 p = name;
6705                 do {
6706                         if (*p == '\\')
6707                                 p++;
6708                         *enddir++ = *p;
6709                 } while (*p++);
6710                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6711                         addfname(expdir);
6712                 return;
6713         }
6714         endname = p;
6715         if (name < start) {
6716                 p = name;
6717                 do {
6718                         if (*p == '\\')
6719                                 p++;
6720                         *enddir++ = *p++;
6721                 } while (p < start);
6722         }
6723         if (enddir == expdir) {
6724                 cp = ".";
6725         } else if (enddir == expdir + 1 && *expdir == '/') {
6726                 cp = "/";
6727         } else {
6728                 cp = expdir;
6729                 enddir[-1] = '\0';
6730         }
6731         dirp = opendir(cp);
6732         if (dirp == NULL)
6733                 return;
6734         if (enddir != expdir)
6735                 enddir[-1] = '/';
6736         if (*endname == 0) {
6737                 atend = 1;
6738         } else {
6739                 atend = 0;
6740                 *endname++ = '\0';
6741         }
6742         matchdot = 0;
6743         p = start;
6744         if (*p == '\\')
6745                 p++;
6746         if (*p == '.')
6747                 matchdot++;
6748         while (!intpending && (dp = readdir(dirp)) != NULL) {
6749                 if (dp->d_name[0] == '.' && !matchdot)
6750                         continue;
6751                 if (pmatch(start, dp->d_name)) {
6752                         if (atend) {
6753                                 strcpy(enddir, dp->d_name);
6754                                 addfname(expdir);
6755                         } else {
6756                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6757                                         continue;
6758                                 p[-1] = '/';
6759                                 expmeta(p, endname);
6760                         }
6761                 }
6762         }
6763         closedir(dirp);
6764         if (!atend)
6765                 endname[-1] = '/';
6766 }
6767
6768 static struct strlist *
6769 msort(struct strlist *list, int len)
6770 {
6771         struct strlist *p, *q = NULL;
6772         struct strlist **lpp;
6773         int half;
6774         int n;
6775
6776         if (len <= 1)
6777                 return list;
6778         half = len >> 1;
6779         p = list;
6780         for (n = half; --n >= 0;) {
6781                 q = p;
6782                 p = p->next;
6783         }
6784         q->next = NULL;                 /* terminate first half of list */
6785         q = msort(list, half);          /* sort first half of list */
6786         p = msort(p, len - half);               /* sort second half */
6787         lpp = &list;
6788         for (;;) {
6789 #if ENABLE_LOCALE_SUPPORT
6790                 if (strcoll(p->text, q->text) < 0)
6791 #else
6792                 if (strcmp(p->text, q->text) < 0)
6793 #endif
6794                                                 {
6795                         *lpp = p;
6796                         lpp = &p->next;
6797                         p = *lpp;
6798                         if (p == NULL) {
6799                                 *lpp = q;
6800                                 break;
6801                         }
6802                 } else {
6803                         *lpp = q;
6804                         lpp = &q->next;
6805                         q = *lpp;
6806                         if (q == NULL) {
6807                                 *lpp = p;
6808                                 break;
6809                         }
6810                 }
6811         }
6812         return list;
6813 }
6814
6815 /*
6816  * Sort the results of file name expansion.  It calculates the number of
6817  * strings to sort and then calls msort (short for merge sort) to do the
6818  * work.
6819  */
6820 static struct strlist *
6821 expsort(struct strlist *str)
6822 {
6823         int len;
6824         struct strlist *sp;
6825
6826         len = 0;
6827         for (sp = str; sp; sp = sp->next)
6828                 len++;
6829         return msort(str, len);
6830 }
6831
6832 static void
6833 expandmeta(struct strlist *str /*, int flag*/)
6834 {
6835         static const char metachars[] ALIGN1 = {
6836                 '*', '?', '[', 0
6837         };
6838         /* TODO - EXP_REDIR */
6839
6840         while (str) {
6841                 struct strlist **savelastp;
6842                 struct strlist *sp;
6843                 char *p;
6844
6845                 if (fflag)
6846                         goto nometa;
6847                 if (!strpbrk(str->text, metachars))
6848                         goto nometa;
6849                 savelastp = exparg.lastp;
6850
6851                 INT_OFF;
6852                 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6853                 {
6854                         int i = strlen(str->text);
6855                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6856                 }
6857
6858                 expmeta(expdir, p);
6859                 free(expdir);
6860                 if (p != str->text)
6861                         free(p);
6862                 INT_ON;
6863                 if (exparg.lastp == savelastp) {
6864                         /*
6865                          * no matches
6866                          */
6867  nometa:
6868                         *exparg.lastp = str;
6869                         rmescapes(str->text);
6870                         exparg.lastp = &str->next;
6871                 } else {
6872                         *exparg.lastp = NULL;
6873                         *savelastp = sp = expsort(*savelastp);
6874                         while (sp->next != NULL)
6875                                 sp = sp->next;
6876                         exparg.lastp = &sp->next;
6877                 }
6878                 str = str->next;
6879         }
6880 }
6881
6882 /*
6883  * Perform variable substitution and command substitution on an argument,
6884  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
6885  * perform splitting and file name expansion.  When arglist is NULL, perform
6886  * here document expansion.
6887  */
6888 static void
6889 expandarg(union node *arg, struct arglist *arglist, int flag)
6890 {
6891         struct strlist *sp;
6892         char *p;
6893
6894         argbackq = arg->narg.backquote;
6895         STARTSTACKSTR(expdest);
6896         ifsfirst.next = NULL;
6897         ifslastp = NULL;
6898         argstr(arg->narg.text, flag,
6899                         /* var_str_list: */ arglist ? arglist->list : NULL);
6900         p = _STPUTC('\0', expdest);
6901         expdest = p - 1;
6902         if (arglist == NULL) {
6903                 return;                 /* here document expanded */
6904         }
6905         p = grabstackstr(p);
6906         exparg.lastp = &exparg.list;
6907         /*
6908          * TODO - EXP_REDIR
6909          */
6910         if (flag & EXP_FULL) {
6911                 ifsbreakup(p, &exparg);
6912                 *exparg.lastp = NULL;
6913                 exparg.lastp = &exparg.list;
6914                 expandmeta(exparg.list /*, flag*/);
6915         } else {
6916                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6917                         rmescapes(p);
6918                 sp = stzalloc(sizeof(*sp));
6919                 sp->text = p;
6920                 *exparg.lastp = sp;
6921                 exparg.lastp = &sp->next;
6922         }
6923         if (ifsfirst.next)
6924                 ifsfree();
6925         *exparg.lastp = NULL;
6926         if (exparg.list) {
6927                 *arglist->lastp = exparg.list;
6928                 arglist->lastp = exparg.lastp;
6929         }
6930 }
6931
6932 /*
6933  * Expand shell variables and backquotes inside a here document.
6934  */
6935 static void
6936 expandhere(union node *arg, int fd)
6937 {
6938         herefd = fd;
6939         expandarg(arg, (struct arglist *)NULL, 0);
6940         full_write(fd, stackblock(), expdest - (char *)stackblock());
6941 }
6942
6943 /*
6944  * Returns true if the pattern matches the string.
6945  */
6946 static int
6947 patmatch(char *pattern, const char *string)
6948 {
6949         return pmatch(preglob(pattern, 0, 0), string);
6950 }
6951
6952 /*
6953  * See if a pattern matches in a case statement.
6954  */
6955 static int
6956 casematch(union node *pattern, char *val)
6957 {
6958         struct stackmark smark;
6959         int result;
6960
6961         setstackmark(&smark);
6962         argbackq = pattern->narg.backquote;
6963         STARTSTACKSTR(expdest);
6964         ifslastp = NULL;
6965         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6966                         /* var_str_list: */ NULL);
6967         STACKSTRNUL(expdest);
6968         result = patmatch(stackblock(), val);
6969         popstackmark(&smark);
6970         return result;
6971 }
6972
6973
6974 /* ============ find_command */
6975
6976 struct builtincmd {
6977         const char *name;
6978         int (*builtin)(int, char **);
6979         /* unsigned flags; */
6980 };
6981 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6982 /* "regular" builtins always take precedence over commands,
6983  * regardless of PATH=....%builtin... position */
6984 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6985 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
6986
6987 struct cmdentry {
6988         smallint cmdtype;       /* CMDxxx */
6989         union param {
6990                 int index;
6991                 /* index >= 0 for commands without path (slashes) */
6992                 /* (TODO: what exactly does the value mean? PATH position?) */
6993                 /* index == -1 for commands with slashes */
6994                 /* index == (-2 - applet_no) for NOFORK applets */
6995                 const struct builtincmd *cmd;
6996                 struct funcnode *func;
6997         } u;
6998 };
6999 /* values of cmdtype */
7000 #define CMDUNKNOWN      -1      /* no entry in table for command */
7001 #define CMDNORMAL       0       /* command is an executable program */
7002 #define CMDFUNCTION     1       /* command is a shell function */
7003 #define CMDBUILTIN      2       /* command is a shell builtin */
7004
7005 /* action to find_command() */
7006 #define DO_ERR          0x01    /* prints errors */
7007 #define DO_ABS          0x02    /* checks absolute paths */
7008 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7009 #define DO_ALTPATH      0x08    /* using alternate path */
7010 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7011
7012 static void find_command(char *, struct cmdentry *, int, const char *);
7013
7014
7015 /* ============ Hashing commands */
7016
7017 /*
7018  * When commands are first encountered, they are entered in a hash table.
7019  * This ensures that a full path search will not have to be done for them
7020  * on each invocation.
7021  *
7022  * We should investigate converting to a linear search, even though that
7023  * would make the command name "hash" a misnomer.
7024  */
7025
7026 struct tblentry {
7027         struct tblentry *next;  /* next entry in hash chain */
7028         union param param;      /* definition of builtin function */
7029         smallint cmdtype;       /* CMDxxx */
7030         char rehash;            /* if set, cd done since entry created */
7031         char cmdname[1];        /* name of command */
7032 };
7033
7034 static struct tblentry **cmdtable;
7035 #define INIT_G_cmdtable() do { \
7036         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7037 } while (0)
7038
7039 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7040
7041
7042 static void
7043 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7044 {
7045         int repeated = 0;
7046
7047 #if ENABLE_FEATURE_SH_STANDALONE
7048         if (applet_no >= 0) {
7049                 if (APPLET_IS_NOEXEC(applet_no)) {
7050                         while (*envp)
7051                                 putenv(*envp++);
7052                         run_applet_no_and_exit(applet_no, argv);
7053                 }
7054                 /* re-exec ourselves with the new arguments */
7055                 execve(bb_busybox_exec_path, argv, envp);
7056                 /* If they called chroot or otherwise made the binary no longer
7057                  * executable, fall through */
7058         }
7059 #endif
7060
7061  repeat:
7062 #ifdef SYSV
7063         do {
7064                 execve(cmd, argv, envp);
7065         } while (errno == EINTR);
7066 #else
7067         execve(cmd, argv, envp);
7068 #endif
7069         if (repeated) {
7070                 free(argv);
7071                 return;
7072         }
7073         if (errno == ENOEXEC) {
7074                 char **ap;
7075                 char **new;
7076
7077                 for (ap = argv; *ap; ap++)
7078                         continue;
7079                 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7080                 ap[1] = cmd;
7081                 ap[0] = cmd = (char *)DEFAULT_SHELL;
7082                 ap += 2;
7083                 argv++;
7084                 while ((*ap++ = *argv++) != NULL)
7085                         continue;
7086                 argv = new;
7087                 repeated++;
7088                 goto repeat;
7089         }
7090 }
7091
7092 /*
7093  * Exec a program.  Never returns.  If you change this routine, you may
7094  * have to change the find_command routine as well.
7095  */
7096 static void shellexec(char **, const char *, int) NORETURN;
7097 static void
7098 shellexec(char **argv, const char *path, int idx)
7099 {
7100         char *cmdname;
7101         int e;
7102         char **envp;
7103         int exerrno;
7104 #if ENABLE_FEATURE_SH_STANDALONE
7105         int applet_no = -1;
7106 #endif
7107
7108         clearredir(/*drop:*/ 1);
7109         envp = listvars(VEXPORT, VUNSET, 0);
7110         if (strchr(argv[0], '/') != NULL
7111 #if ENABLE_FEATURE_SH_STANDALONE
7112          || (applet_no = find_applet_by_name(argv[0])) >= 0
7113 #endif
7114         ) {
7115                 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7116                 e = errno;
7117         } else {
7118                 e = ENOENT;
7119                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7120                         if (--idx < 0 && pathopt == NULL) {
7121                                 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7122                                 if (errno != ENOENT && errno != ENOTDIR)
7123                                         e = errno;
7124                         }
7125                         stunalloc(cmdname);
7126                 }
7127         }
7128
7129         /* Map to POSIX errors */
7130         switch (e) {
7131         case EACCES:
7132                 exerrno = 126;
7133                 break;
7134         case ENOENT:
7135                 exerrno = 127;
7136                 break;
7137         default:
7138                 exerrno = 2;
7139                 break;
7140         }
7141         exitstatus = exerrno;
7142         TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7143                 argv[0], e, suppressint));
7144         ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7145         /* NOTREACHED */
7146 }
7147
7148 static void
7149 printentry(struct tblentry *cmdp)
7150 {
7151         int idx;
7152         const char *path;
7153         char *name;
7154
7155         idx = cmdp->param.index;
7156         path = pathval();
7157         do {
7158                 name = padvance(&path, cmdp->cmdname);
7159                 stunalloc(name);
7160         } while (--idx >= 0);
7161         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7162 }
7163
7164 /*
7165  * Clear out command entries.  The argument specifies the first entry in
7166  * PATH which has changed.
7167  */
7168 static void
7169 clearcmdentry(int firstchange)
7170 {
7171         struct tblentry **tblp;
7172         struct tblentry **pp;
7173         struct tblentry *cmdp;
7174
7175         INT_OFF;
7176         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7177                 pp = tblp;
7178                 while ((cmdp = *pp) != NULL) {
7179                         if ((cmdp->cmdtype == CMDNORMAL &&
7180                              cmdp->param.index >= firstchange)
7181                          || (cmdp->cmdtype == CMDBUILTIN &&
7182                              builtinloc >= firstchange)
7183                         ) {
7184                                 *pp = cmdp->next;
7185                                 free(cmdp);
7186                         } else {
7187                                 pp = &cmdp->next;
7188                         }
7189                 }
7190         }
7191         INT_ON;
7192 }
7193
7194 /*
7195  * Locate a command in the command hash table.  If "add" is nonzero,
7196  * add the command to the table if it is not already present.  The
7197  * variable "lastcmdentry" is set to point to the address of the link
7198  * pointing to the entry, so that delete_cmd_entry can delete the
7199  * entry.
7200  *
7201  * Interrupts must be off if called with add != 0.
7202  */
7203 static struct tblentry **lastcmdentry;
7204
7205 static struct tblentry *
7206 cmdlookup(const char *name, int add)
7207 {
7208         unsigned int hashval;
7209         const char *p;
7210         struct tblentry *cmdp;
7211         struct tblentry **pp;
7212
7213         p = name;
7214         hashval = (unsigned char)*p << 4;
7215         while (*p)
7216                 hashval += (unsigned char)*p++;
7217         hashval &= 0x7FFF;
7218         pp = &cmdtable[hashval % CMDTABLESIZE];
7219         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7220                 if (strcmp(cmdp->cmdname, name) == 0)
7221                         break;
7222                 pp = &cmdp->next;
7223         }
7224         if (add && cmdp == NULL) {
7225                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7226                                 + strlen(name)
7227                                 /* + 1 - already done because
7228                                  * tblentry::cmdname is char[1] */);
7229                 /*cmdp->next = NULL; - ckzalloc did it */
7230                 cmdp->cmdtype = CMDUNKNOWN;
7231                 strcpy(cmdp->cmdname, name);
7232         }
7233         lastcmdentry = pp;
7234         return cmdp;
7235 }
7236
7237 /*
7238  * Delete the command entry returned on the last lookup.
7239  */
7240 static void
7241 delete_cmd_entry(void)
7242 {
7243         struct tblentry *cmdp;
7244
7245         INT_OFF;
7246         cmdp = *lastcmdentry;
7247         *lastcmdentry = cmdp->next;
7248         if (cmdp->cmdtype == CMDFUNCTION)
7249                 freefunc(cmdp->param.func);
7250         free(cmdp);
7251         INT_ON;
7252 }
7253
7254 /*
7255  * Add a new command entry, replacing any existing command entry for
7256  * the same name - except special builtins.
7257  */
7258 static void
7259 addcmdentry(char *name, struct cmdentry *entry)
7260 {
7261         struct tblentry *cmdp;
7262
7263         cmdp = cmdlookup(name, 1);
7264         if (cmdp->cmdtype == CMDFUNCTION) {
7265                 freefunc(cmdp->param.func);
7266         }
7267         cmdp->cmdtype = entry->cmdtype;
7268         cmdp->param = entry->u;
7269         cmdp->rehash = 0;
7270 }
7271
7272 static int
7273 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7274 {
7275         struct tblentry **pp;
7276         struct tblentry *cmdp;
7277         int c;
7278         struct cmdentry entry;
7279         char *name;
7280
7281         if (nextopt("r") != '\0') {
7282                 clearcmdentry(0);
7283                 return 0;
7284         }
7285
7286         if (*argptr == NULL) {
7287                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7288                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7289                                 if (cmdp->cmdtype == CMDNORMAL)
7290                                         printentry(cmdp);
7291                         }
7292                 }
7293                 return 0;
7294         }
7295
7296         c = 0;
7297         while ((name = *argptr) != NULL) {
7298                 cmdp = cmdlookup(name, 0);
7299                 if (cmdp != NULL
7300                  && (cmdp->cmdtype == CMDNORMAL
7301                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7302                 ) {
7303                         delete_cmd_entry();
7304                 }
7305                 find_command(name, &entry, DO_ERR, pathval());
7306                 if (entry.cmdtype == CMDUNKNOWN)
7307                         c = 1;
7308                 argptr++;
7309         }
7310         return c;
7311 }
7312
7313 /*
7314  * Called when a cd is done.  Marks all commands so the next time they
7315  * are executed they will be rehashed.
7316  */
7317 static void
7318 hashcd(void)
7319 {
7320         struct tblentry **pp;
7321         struct tblentry *cmdp;
7322
7323         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7324                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7325                         if (cmdp->cmdtype == CMDNORMAL
7326                          || (cmdp->cmdtype == CMDBUILTIN
7327                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7328                              && builtinloc > 0)
7329                         ) {
7330                                 cmdp->rehash = 1;
7331                         }
7332                 }
7333         }
7334 }
7335
7336 /*
7337  * Fix command hash table when PATH changed.
7338  * Called before PATH is changed.  The argument is the new value of PATH;
7339  * pathval() still returns the old value at this point.
7340  * Called with interrupts off.
7341  */
7342 static void
7343 changepath(const char *new)
7344 {
7345         const char *old;
7346         int firstchange;
7347         int idx;
7348         int idx_bltin;
7349
7350         old = pathval();
7351         firstchange = 9999;     /* assume no change */
7352         idx = 0;
7353         idx_bltin = -1;
7354         for (;;) {
7355                 if (*old != *new) {
7356                         firstchange = idx;
7357                         if ((*old == '\0' && *new == ':')
7358                          || (*old == ':' && *new == '\0'))
7359                                 firstchange++;
7360                         old = new;      /* ignore subsequent differences */
7361                 }
7362                 if (*new == '\0')
7363                         break;
7364                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7365                         idx_bltin = idx;
7366                 if (*new == ':')
7367                         idx++;
7368                 new++, old++;
7369         }
7370         if (builtinloc < 0 && idx_bltin >= 0)
7371                 builtinloc = idx_bltin;             /* zap builtins */
7372         if (builtinloc >= 0 && idx_bltin < 0)
7373                 firstchange = 0;
7374         clearcmdentry(firstchange);
7375         builtinloc = idx_bltin;
7376 }
7377
7378 #define TEOF 0
7379 #define TNL 1
7380 #define TREDIR 2
7381 #define TWORD 3
7382 #define TSEMI 4
7383 #define TBACKGND 5
7384 #define TAND 6
7385 #define TOR 7
7386 #define TPIPE 8
7387 #define TLP 9
7388 #define TRP 10
7389 #define TENDCASE 11
7390 #define TENDBQUOTE 12
7391 #define TNOT 13
7392 #define TCASE 14
7393 #define TDO 15
7394 #define TDONE 16
7395 #define TELIF 17
7396 #define TELSE 18
7397 #define TESAC 19
7398 #define TFI 20
7399 #define TFOR 21
7400 #define TIF 22
7401 #define TIN 23
7402 #define TTHEN 24
7403 #define TUNTIL 25
7404 #define TWHILE 26
7405 #define TBEGIN 27
7406 #define TEND 28
7407 typedef smallint token_id_t;
7408
7409 /* first char is indicating which tokens mark the end of a list */
7410 static const char *const tokname_array[] = {
7411         "\1end of file",
7412         "\0newline",
7413         "\0redirection",
7414         "\0word",
7415         "\0;",
7416         "\0&",
7417         "\0&&",
7418         "\0||",
7419         "\0|",
7420         "\0(",
7421         "\1)",
7422         "\1;;",
7423         "\1`",
7424 #define KWDOFFSET 13
7425         /* the following are keywords */
7426         "\0!",
7427         "\0case",
7428         "\1do",
7429         "\1done",
7430         "\1elif",
7431         "\1else",
7432         "\1esac",
7433         "\1fi",
7434         "\0for",
7435         "\0if",
7436         "\0in",
7437         "\1then",
7438         "\0until",
7439         "\0while",
7440         "\0{",
7441         "\1}",
7442 };
7443
7444 static const char *
7445 tokname(int tok)
7446 {
7447         static char buf[16];
7448
7449 //try this:
7450 //if (tok < TSEMI) return tokname_array[tok] + 1;
7451 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7452 //return buf;
7453
7454         if (tok >= TSEMI)
7455                 buf[0] = '"';
7456         sprintf(buf + (tok >= TSEMI), "%s%c",
7457                         tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7458         return buf;
7459 }
7460
7461 /* Wrapper around strcmp for qsort/bsearch/... */
7462 static int
7463 pstrcmp(const void *a, const void *b)
7464 {
7465         return strcmp((char*) a, (*(char**) b) + 1);
7466 }
7467
7468 static const char *const *
7469 findkwd(const char *s)
7470 {
7471         return bsearch(s, tokname_array + KWDOFFSET,
7472                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
7473                         sizeof(tokname_array[0]), pstrcmp);
7474 }
7475
7476 /*
7477  * Locate and print what a word is...
7478  */
7479 static int
7480 describe_command(char *command, int describe_command_verbose)
7481 {
7482         struct cmdentry entry;
7483         struct tblentry *cmdp;
7484 #if ENABLE_ASH_ALIAS
7485         const struct alias *ap;
7486 #endif
7487         const char *path = pathval();
7488
7489         if (describe_command_verbose) {
7490                 out1str(command);
7491         }
7492
7493         /* First look at the keywords */
7494         if (findkwd(command)) {
7495                 out1str(describe_command_verbose ? " is a shell keyword" : command);
7496                 goto out;
7497         }
7498
7499 #if ENABLE_ASH_ALIAS
7500         /* Then look at the aliases */
7501         ap = lookupalias(command, 0);
7502         if (ap != NULL) {
7503                 if (!describe_command_verbose) {
7504                         out1str("alias ");
7505                         printalias(ap);
7506                         return 0;
7507                 }
7508                 out1fmt(" is an alias for %s", ap->val);
7509                 goto out;
7510         }
7511 #endif
7512         /* Then check if it is a tracked alias */
7513         cmdp = cmdlookup(command, 0);
7514         if (cmdp != NULL) {
7515                 entry.cmdtype = cmdp->cmdtype;
7516                 entry.u = cmdp->param;
7517         } else {
7518                 /* Finally use brute force */
7519                 find_command(command, &entry, DO_ABS, path);
7520         }
7521
7522         switch (entry.cmdtype) {
7523         case CMDNORMAL: {
7524                 int j = entry.u.index;
7525                 char *p;
7526                 if (j < 0) {
7527                         p = command;
7528                 } else {
7529                         do {
7530                                 p = padvance(&path, command);
7531                                 stunalloc(p);
7532                         } while (--j >= 0);
7533                 }
7534                 if (describe_command_verbose) {
7535                         out1fmt(" is%s %s",
7536                                 (cmdp ? " a tracked alias for" : nullstr), p
7537                         );
7538                 } else {
7539                         out1str(p);
7540                 }
7541                 break;
7542         }
7543
7544         case CMDFUNCTION:
7545                 if (describe_command_verbose) {
7546                         out1str(" is a shell function");
7547                 } else {
7548                         out1str(command);
7549                 }
7550                 break;
7551
7552         case CMDBUILTIN:
7553                 if (describe_command_verbose) {
7554                         out1fmt(" is a %sshell builtin",
7555                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7556                                         "special " : nullstr
7557                         );
7558                 } else {
7559                         out1str(command);
7560                 }
7561                 break;
7562
7563         default:
7564                 if (describe_command_verbose) {
7565                         out1str(": not found\n");
7566                 }
7567                 return 127;
7568         }
7569  out:
7570         outstr("\n", stdout);
7571         return 0;
7572 }
7573
7574 static int
7575 typecmd(int argc UNUSED_PARAM, char **argv)
7576 {
7577         int i = 1;
7578         int err = 0;
7579         int verbose = 1;
7580
7581         /* type -p ... ? (we don't bother checking for 'p') */
7582         if (argv[1] && argv[1][0] == '-') {
7583                 i++;
7584                 verbose = 0;
7585         }
7586         while (argv[i]) {
7587                 err |= describe_command(argv[i++], verbose);
7588         }
7589         return err;
7590 }
7591
7592 #if ENABLE_ASH_CMDCMD
7593 static int
7594 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7595 {
7596         int c;
7597         enum {
7598                 VERIFY_BRIEF = 1,
7599                 VERIFY_VERBOSE = 2,
7600         } verify = 0;
7601
7602         while ((c = nextopt("pvV")) != '\0')
7603                 if (c == 'V')
7604                         verify |= VERIFY_VERBOSE;
7605                 else if (c == 'v')
7606                         verify |= VERIFY_BRIEF;
7607 #if DEBUG
7608                 else if (c != 'p')
7609                         abort();
7610 #endif
7611         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7612         if (verify && (*argptr != NULL)) {
7613                 return describe_command(*argptr, verify - VERIFY_BRIEF);
7614         }
7615
7616         return 0;
7617 }
7618 #endif
7619
7620
7621 /* ============ eval.c */
7622
7623 static int funcblocksize;       /* size of structures in function */
7624 static int funcstringsize;      /* size of strings in node */
7625 static void *funcblock;         /* block to allocate function from */
7626 static char *funcstring;        /* block to allocate strings from */
7627
7628 /* flags in argument to evaltree */
7629 #define EV_EXIT    01           /* exit after evaluating tree */
7630 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
7631 #define EV_BACKCMD 04           /* command executing within back quotes */
7632
7633 static const short nodesize[N_NUMBER] = {
7634         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
7635         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
7636         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
7637         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7638         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7639         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
7640         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
7641         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
7642         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
7643         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
7644         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
7645         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
7646         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
7647         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
7648         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
7649         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
7650         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
7651 #if ENABLE_ASH_BASH_COMPAT
7652         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
7653 #endif
7654         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7655         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
7656         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
7657         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
7658         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
7659         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
7660         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
7661         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
7662         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
7663 };
7664
7665 static void calcsize(union node *n);
7666
7667 static void
7668 sizenodelist(struct nodelist *lp)
7669 {
7670         while (lp) {
7671                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7672                 calcsize(lp->n);
7673                 lp = lp->next;
7674         }
7675 }
7676
7677 static void
7678 calcsize(union node *n)
7679 {
7680         if (n == NULL)
7681                 return;
7682         funcblocksize += nodesize[n->type];
7683         switch (n->type) {
7684         case NCMD:
7685                 calcsize(n->ncmd.redirect);
7686                 calcsize(n->ncmd.args);
7687                 calcsize(n->ncmd.assign);
7688                 break;
7689         case NPIPE:
7690                 sizenodelist(n->npipe.cmdlist);
7691                 break;
7692         case NREDIR:
7693         case NBACKGND:
7694         case NSUBSHELL:
7695                 calcsize(n->nredir.redirect);
7696                 calcsize(n->nredir.n);
7697                 break;
7698         case NAND:
7699         case NOR:
7700         case NSEMI:
7701         case NWHILE:
7702         case NUNTIL:
7703                 calcsize(n->nbinary.ch2);
7704                 calcsize(n->nbinary.ch1);
7705                 break;
7706         case NIF:
7707                 calcsize(n->nif.elsepart);
7708                 calcsize(n->nif.ifpart);
7709                 calcsize(n->nif.test);
7710                 break;
7711         case NFOR:
7712                 funcstringsize += strlen(n->nfor.var) + 1;
7713                 calcsize(n->nfor.body);
7714                 calcsize(n->nfor.args);
7715                 break;
7716         case NCASE:
7717                 calcsize(n->ncase.cases);
7718                 calcsize(n->ncase.expr);
7719                 break;
7720         case NCLIST:
7721                 calcsize(n->nclist.body);
7722                 calcsize(n->nclist.pattern);
7723                 calcsize(n->nclist.next);
7724                 break;
7725         case NDEFUN:
7726         case NARG:
7727                 sizenodelist(n->narg.backquote);
7728                 funcstringsize += strlen(n->narg.text) + 1;
7729                 calcsize(n->narg.next);
7730                 break;
7731         case NTO:
7732 #if ENABLE_ASH_BASH_COMPAT
7733         case NTO2:
7734 #endif
7735         case NCLOBBER:
7736         case NFROM:
7737         case NFROMTO:
7738         case NAPPEND:
7739                 calcsize(n->nfile.fname);
7740                 calcsize(n->nfile.next);
7741                 break;
7742         case NTOFD:
7743         case NFROMFD:
7744                 calcsize(n->ndup.vname);
7745                 calcsize(n->ndup.next);
7746         break;
7747         case NHERE:
7748         case NXHERE:
7749                 calcsize(n->nhere.doc);
7750                 calcsize(n->nhere.next);
7751                 break;
7752         case NNOT:
7753                 calcsize(n->nnot.com);
7754                 break;
7755         };
7756 }
7757
7758 static char *
7759 nodeckstrdup(char *s)
7760 {
7761         char *rtn = funcstring;
7762
7763         strcpy(funcstring, s);
7764         funcstring += strlen(s) + 1;
7765         return rtn;
7766 }
7767
7768 static union node *copynode(union node *);
7769
7770 static struct nodelist *
7771 copynodelist(struct nodelist *lp)
7772 {
7773         struct nodelist *start;
7774         struct nodelist **lpp;
7775
7776         lpp = &start;
7777         while (lp) {
7778                 *lpp = funcblock;
7779                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7780                 (*lpp)->n = copynode(lp->n);
7781                 lp = lp->next;
7782                 lpp = &(*lpp)->next;
7783         }
7784         *lpp = NULL;
7785         return start;
7786 }
7787
7788 static union node *
7789 copynode(union node *n)
7790 {
7791         union node *new;
7792
7793         if (n == NULL)
7794                 return NULL;
7795         new = funcblock;
7796         funcblock = (char *) funcblock + nodesize[n->type];
7797
7798         switch (n->type) {
7799         case NCMD:
7800                 new->ncmd.redirect = copynode(n->ncmd.redirect);
7801                 new->ncmd.args = copynode(n->ncmd.args);
7802                 new->ncmd.assign = copynode(n->ncmd.assign);
7803                 break;
7804         case NPIPE:
7805                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7806                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7807                 break;
7808         case NREDIR:
7809         case NBACKGND:
7810         case NSUBSHELL:
7811                 new->nredir.redirect = copynode(n->nredir.redirect);
7812                 new->nredir.n = copynode(n->nredir.n);
7813                 break;
7814         case NAND:
7815         case NOR:
7816         case NSEMI:
7817         case NWHILE:
7818         case NUNTIL:
7819                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7820                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7821                 break;
7822         case NIF:
7823                 new->nif.elsepart = copynode(n->nif.elsepart);
7824                 new->nif.ifpart = copynode(n->nif.ifpart);
7825                 new->nif.test = copynode(n->nif.test);
7826                 break;
7827         case NFOR:
7828                 new->nfor.var = nodeckstrdup(n->nfor.var);
7829                 new->nfor.body = copynode(n->nfor.body);
7830                 new->nfor.args = copynode(n->nfor.args);
7831                 break;
7832         case NCASE:
7833                 new->ncase.cases = copynode(n->ncase.cases);
7834                 new->ncase.expr = copynode(n->ncase.expr);
7835                 break;
7836         case NCLIST:
7837                 new->nclist.body = copynode(n->nclist.body);
7838                 new->nclist.pattern = copynode(n->nclist.pattern);
7839                 new->nclist.next = copynode(n->nclist.next);
7840                 break;
7841         case NDEFUN:
7842         case NARG:
7843                 new->narg.backquote = copynodelist(n->narg.backquote);
7844                 new->narg.text = nodeckstrdup(n->narg.text);
7845                 new->narg.next = copynode(n->narg.next);
7846                 break;
7847         case NTO:
7848 #if ENABLE_ASH_BASH_COMPAT
7849         case NTO2:
7850 #endif
7851         case NCLOBBER:
7852         case NFROM:
7853         case NFROMTO:
7854         case NAPPEND:
7855                 new->nfile.fname = copynode(n->nfile.fname);
7856                 new->nfile.fd = n->nfile.fd;
7857                 new->nfile.next = copynode(n->nfile.next);
7858                 break;
7859         case NTOFD:
7860         case NFROMFD:
7861                 new->ndup.vname = copynode(n->ndup.vname);
7862                 new->ndup.dupfd = n->ndup.dupfd;
7863                 new->ndup.fd = n->ndup.fd;
7864                 new->ndup.next = copynode(n->ndup.next);
7865                 break;
7866         case NHERE:
7867         case NXHERE:
7868                 new->nhere.doc = copynode(n->nhere.doc);
7869                 new->nhere.fd = n->nhere.fd;
7870                 new->nhere.next = copynode(n->nhere.next);
7871                 break;
7872         case NNOT:
7873                 new->nnot.com = copynode(n->nnot.com);
7874                 break;
7875         };
7876         new->type = n->type;
7877         return new;
7878 }
7879
7880 /*
7881  * Make a copy of a parse tree.
7882  */
7883 static struct funcnode *
7884 copyfunc(union node *n)
7885 {
7886         struct funcnode *f;
7887         size_t blocksize;
7888
7889         funcblocksize = offsetof(struct funcnode, n);
7890         funcstringsize = 0;
7891         calcsize(n);
7892         blocksize = funcblocksize;
7893         f = ckmalloc(blocksize + funcstringsize);
7894         funcblock = (char *) f + offsetof(struct funcnode, n);
7895         funcstring = (char *) f + blocksize;
7896         copynode(n);
7897         f->count = 0;
7898         return f;
7899 }
7900
7901 /*
7902  * Define a shell function.
7903  */
7904 static void
7905 defun(char *name, union node *func)
7906 {
7907         struct cmdentry entry;
7908
7909         INT_OFF;
7910         entry.cmdtype = CMDFUNCTION;
7911         entry.u.func = copyfunc(func);
7912         addcmdentry(name, &entry);
7913         INT_ON;
7914 }
7915
7916 static int evalskip;            /* set if we are skipping commands */
7917 /* reasons for skipping commands (see comment on breakcmd routine) */
7918 #define SKIPBREAK      (1 << 0)
7919 #define SKIPCONT       (1 << 1)
7920 #define SKIPFUNC       (1 << 2)
7921 #define SKIPFILE       (1 << 3)
7922 #define SKIPEVAL       (1 << 4)
7923 static int skipcount;           /* number of levels to skip */
7924 static int funcnest;            /* depth of function calls */
7925 static int loopnest;            /* current loop nesting level */
7926
7927 /* forward decl way out to parsing code - dotrap needs it */
7928 static int evalstring(char *s, int mask);
7929
7930 /*
7931  * Called to execute a trap.  Perhaps we should avoid entering new trap
7932  * handlers while we are executing a trap handler.
7933  */
7934 static int
7935 dotrap(void)
7936 {
7937         char *p;
7938         char *q;
7939         int i;
7940         int savestatus;
7941         int skip;
7942
7943         savestatus = exitstatus;
7944         pendingsig = 0;
7945         xbarrier();
7946
7947         for (i = 1, q = gotsig; i < NSIG; i++, q++) {
7948                 if (!*q)
7949                         continue;
7950                 *q = '\0';
7951
7952                 p = trap[i];
7953                 if (!p)
7954                         continue;
7955                 skip = evalstring(p, SKIPEVAL);
7956                 exitstatus = savestatus;
7957                 if (skip)
7958                         return skip;
7959         }
7960
7961         return 0;
7962 }
7963
7964 /* forward declarations - evaluation is fairly recursive business... */
7965 static void evalloop(union node *, int);
7966 static void evalfor(union node *, int);
7967 static void evalcase(union node *, int);
7968 static void evalsubshell(union node *, int);
7969 static void expredir(union node *);
7970 static void evalpipe(union node *, int);
7971 static void evalcommand(union node *, int);
7972 static int evalbltin(const struct builtincmd *, int, char **);
7973 static void prehash(union node *);
7974
7975 /*
7976  * Evaluate a parse tree.  The value is left in the global variable
7977  * exitstatus.
7978  */
7979 static void
7980 evaltree(union node *n, int flags)
7981 {
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 == 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;
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. */
11688         setinputstring((char *)ps);
11689         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11690         popfile();
11691
11692         n.narg.type = NARG;
11693         n.narg.next = NULL;
11694         n.narg.text = wordtext;
11695         n.narg.backquote = backquotelist;
11696
11697         expandarg(&n, NULL, 0);
11698         return stackblock();
11699 }
11700 #endif
11701
11702 /*
11703  * Execute a command or commands contained in a string.
11704  */
11705 static int
11706 evalstring(char *s, int mask)
11707 {
11708         union node *n;
11709         struct stackmark smark;
11710         int skip;
11711
11712         setinputstring(s);
11713         setstackmark(&smark);
11714
11715         skip = 0;
11716         while ((n = parsecmd(0)) != NEOF) {
11717                 evaltree(n, 0);
11718                 popstackmark(&smark);
11719                 skip = evalskip;
11720                 if (skip)
11721                         break;
11722         }
11723         popfile();
11724
11725         skip &= mask;
11726         evalskip = skip;
11727         return skip;
11728 }
11729
11730 /*
11731  * The eval command.
11732  */
11733 static int
11734 evalcmd(int argc UNUSED_PARAM, char **argv)
11735 {
11736         char *p;
11737         char *concat;
11738
11739         if (argv[1]) {
11740                 p = argv[1];
11741                 argv += 2;
11742                 if (argv[0]) {
11743                         STARTSTACKSTR(concat);
11744                         for (;;) {
11745                                 concat = stack_putstr(p, concat);
11746                                 p = *argv++;
11747                                 if (p == NULL)
11748                                         break;
11749                                 STPUTC(' ', concat);
11750                         }
11751                         STPUTC('\0', concat);
11752                         p = grabstackstr(concat);
11753                 }
11754                 evalstring(p, ~SKIPEVAL);
11755
11756         }
11757         return exitstatus;
11758 }
11759
11760 /*
11761  * Read and execute commands.  "Top" is nonzero for the top level command
11762  * loop; it turns on prompting if the shell is interactive.
11763  */
11764 static int
11765 cmdloop(int top)
11766 {
11767         union node *n;
11768         struct stackmark smark;
11769         int inter;
11770         int numeof = 0;
11771
11772         TRACE(("cmdloop(%d) called\n", top));
11773         for (;;) {
11774                 int skip;
11775
11776                 setstackmark(&smark);
11777 #if JOBS
11778                 if (doing_jobctl)
11779                         showjobs(stderr, SHOW_CHANGED);
11780 #endif
11781                 inter = 0;
11782                 if (iflag && top) {
11783                         inter++;
11784 #if ENABLE_ASH_MAIL
11785                         chkmail();
11786 #endif
11787                 }
11788                 n = parsecmd(inter);
11789                 /* showtree(n); DEBUG */
11790                 if (n == NEOF) {
11791                         if (!top || numeof >= 50)
11792                                 break;
11793                         if (!stoppedjobs()) {
11794                                 if (!Iflag)
11795                                         break;
11796                                 out2str("\nUse \"exit\" to leave shell.\n");
11797                         }
11798                         numeof++;
11799                 } else if (nflag == 0) {
11800                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11801                         job_warning >>= 1;
11802                         numeof = 0;
11803                         evaltree(n, 0);
11804                 }
11805                 popstackmark(&smark);
11806                 skip = evalskip;
11807
11808                 if (skip) {
11809                         evalskip = 0;
11810                         return skip & SKIPEVAL;
11811                 }
11812         }
11813         return 0;
11814 }
11815
11816 /*
11817  * Take commands from a file.  To be compatible we should do a path
11818  * search for the file, which is necessary to find sub-commands.
11819  */
11820 static char *
11821 find_dot_file(char *name)
11822 {
11823         char *fullname;
11824         const char *path = pathval();
11825         struct stat statb;
11826
11827         /* don't try this for absolute or relative paths */
11828         if (strchr(name, '/'))
11829                 return name;
11830
11831         while ((fullname = padvance(&path, name)) != NULL) {
11832                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11833                         /*
11834                          * Don't bother freeing here, since it will
11835                          * be freed by the caller.
11836                          */
11837                         return fullname;
11838                 }
11839                 stunalloc(fullname);
11840         }
11841
11842         /* not found in the PATH */
11843         ash_msg_and_raise_error("%s: not found", name);
11844         /* NOTREACHED */
11845 }
11846
11847 static int
11848 dotcmd(int argc, char **argv)
11849 {
11850         struct strlist *sp;
11851         volatile struct shparam saveparam;
11852         int status = 0;
11853
11854         for (sp = cmdenviron; sp; sp = sp->next)
11855                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11856
11857         if (argv[1]) {        /* That's what SVR2 does */
11858                 char *fullname = find_dot_file(argv[1]);
11859                 argv += 2;
11860                 argc -= 2;
11861                 if (argc) { /* argc > 0, argv[0] != NULL */
11862                         saveparam = shellparam;
11863                         shellparam.malloced = 0;
11864                         shellparam.nparam = argc;
11865                         shellparam.p = argv;
11866                 };
11867
11868                 setinputfile(fullname, INPUT_PUSH_FILE);
11869                 commandname = fullname;
11870                 cmdloop(0);
11871                 popfile();
11872
11873                 if (argc) {
11874                         freeparam(&shellparam);
11875                         shellparam = saveparam;
11876                 };
11877                 status = exitstatus;
11878         }
11879         return status;
11880 }
11881
11882 static int
11883 exitcmd(int argc UNUSED_PARAM, char **argv)
11884 {
11885         if (stoppedjobs())
11886                 return 0;
11887         if (argv[1])
11888                 exitstatus = number(argv[1]);
11889         raise_exception(EXEXIT);
11890         /* NOTREACHED */
11891 }
11892
11893 /*
11894  * Read a file containing shell functions.
11895  */
11896 static void
11897 readcmdfile(char *name)
11898 {
11899         setinputfile(name, INPUT_PUSH_FILE);
11900         cmdloop(0);
11901         popfile();
11902 }
11903
11904
11905 /* ============ find_command inplementation */
11906
11907 /*
11908  * Resolve a command name.  If you change this routine, you may have to
11909  * change the shellexec routine as well.
11910  */
11911 static void
11912 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11913 {
11914         struct tblentry *cmdp;
11915         int idx;
11916         int prev;
11917         char *fullname;
11918         struct stat statb;
11919         int e;
11920         int updatetbl;
11921         struct builtincmd *bcmd;
11922
11923         /* If name contains a slash, don't use PATH or hash table */
11924         if (strchr(name, '/') != NULL) {
11925                 entry->u.index = -1;
11926                 if (act & DO_ABS) {
11927                         while (stat(name, &statb) < 0) {
11928 #ifdef SYSV
11929                                 if (errno == EINTR)
11930                                         continue;
11931 #endif
11932                                 entry->cmdtype = CMDUNKNOWN;
11933                                 return;
11934                         }
11935                 }
11936                 entry->cmdtype = CMDNORMAL;
11937                 return;
11938         }
11939
11940 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11941
11942         updatetbl = (path == pathval());
11943         if (!updatetbl) {
11944                 act |= DO_ALTPATH;
11945                 if (strstr(path, "%builtin") != NULL)
11946                         act |= DO_ALTBLTIN;
11947         }
11948
11949         /* If name is in the table, check answer will be ok */
11950         cmdp = cmdlookup(name, 0);
11951         if (cmdp != NULL) {
11952                 int bit;
11953
11954                 switch (cmdp->cmdtype) {
11955                 default:
11956 #if DEBUG
11957                         abort();
11958 #endif
11959                 case CMDNORMAL:
11960                         bit = DO_ALTPATH;
11961                         break;
11962                 case CMDFUNCTION:
11963                         bit = DO_NOFUNC;
11964                         break;
11965                 case CMDBUILTIN:
11966                         bit = DO_ALTBLTIN;
11967                         break;
11968                 }
11969                 if (act & bit) {
11970                         updatetbl = 0;
11971                         cmdp = NULL;
11972                 } else if (cmdp->rehash == 0)
11973                         /* if not invalidated by cd, we're done */
11974                         goto success;
11975         }
11976
11977         /* If %builtin not in path, check for builtin next */
11978         bcmd = find_builtin(name);
11979         if (bcmd) {
11980                 if (IS_BUILTIN_REGULAR(bcmd))
11981                         goto builtin_success;
11982                 if (act & DO_ALTPATH) {
11983                         if (!(act & DO_ALTBLTIN))
11984                                 goto builtin_success;
11985                 } else if (builtinloc <= 0) {
11986                         goto builtin_success;
11987                 }
11988         }
11989
11990 #if ENABLE_FEATURE_SH_STANDALONE
11991         {
11992                 int applet_no = find_applet_by_name(name);
11993                 if (applet_no >= 0) {
11994                         entry->cmdtype = CMDNORMAL;
11995                         entry->u.index = -2 - applet_no;
11996                         return;
11997                 }
11998         }
11999 #endif
12000
12001         /* We have to search path. */
12002         prev = -1;              /* where to start */
12003         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12004                 if (cmdp->cmdtype == CMDBUILTIN)
12005                         prev = builtinloc;
12006                 else
12007                         prev = cmdp->param.index;
12008         }
12009
12010         e = ENOENT;
12011         idx = -1;
12012  loop:
12013         while ((fullname = padvance(&path, name)) != NULL) {
12014                 stunalloc(fullname);
12015                 /* NB: code below will still use fullname
12016                  * despite it being "unallocated" */
12017                 idx++;
12018                 if (pathopt) {
12019                         if (prefix(pathopt, "builtin")) {
12020                                 if (bcmd)
12021                                         goto builtin_success;
12022                                 continue;
12023                         }
12024                         if ((act & DO_NOFUNC)
12025                          || !prefix(pathopt, "func")
12026                         ) {     /* ignore unimplemented options */
12027                                 continue;
12028                         }
12029                 }
12030                 /* if rehash, don't redo absolute path names */
12031                 if (fullname[0] == '/' && idx <= prev) {
12032                         if (idx < prev)
12033                                 continue;
12034                         TRACE(("searchexec \"%s\": no change\n", name));
12035                         goto success;
12036                 }
12037                 while (stat(fullname, &statb) < 0) {
12038 #ifdef SYSV
12039                         if (errno == EINTR)
12040                                 continue;
12041 #endif
12042                         if (errno != ENOENT && errno != ENOTDIR)
12043                                 e = errno;
12044                         goto loop;
12045                 }
12046                 e = EACCES;     /* if we fail, this will be the error */
12047                 if (!S_ISREG(statb.st_mode))
12048                         continue;
12049                 if (pathopt) {          /* this is a %func directory */
12050                         stalloc(strlen(fullname) + 1);
12051                         /* NB: stalloc will return space pointed by fullname
12052                          * (because we don't have any intervening allocations
12053                          * between stunalloc above and this stalloc) */
12054                         readcmdfile(fullname);
12055                         cmdp = cmdlookup(name, 0);
12056                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12057                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12058                         stunalloc(fullname);
12059                         goto success;
12060                 }
12061                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12062                 if (!updatetbl) {
12063                         entry->cmdtype = CMDNORMAL;
12064                         entry->u.index = idx;
12065                         return;
12066                 }
12067                 INT_OFF;
12068                 cmdp = cmdlookup(name, 1);
12069                 cmdp->cmdtype = CMDNORMAL;
12070                 cmdp->param.index = idx;
12071                 INT_ON;
12072                 goto success;
12073         }
12074
12075         /* We failed.  If there was an entry for this command, delete it */
12076         if (cmdp && updatetbl)
12077                 delete_cmd_entry();
12078         if (act & DO_ERR)
12079                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12080         entry->cmdtype = CMDUNKNOWN;
12081         return;
12082
12083  builtin_success:
12084         if (!updatetbl) {
12085                 entry->cmdtype = CMDBUILTIN;
12086                 entry->u.cmd = bcmd;
12087                 return;
12088         }
12089         INT_OFF;
12090         cmdp = cmdlookup(name, 1);
12091         cmdp->cmdtype = CMDBUILTIN;
12092         cmdp->param.cmd = bcmd;
12093         INT_ON;
12094  success:
12095         cmdp->rehash = 0;
12096         entry->cmdtype = cmdp->cmdtype;
12097         entry->u = cmdp->param;
12098 }
12099
12100
12101 /* ============ trap.c */
12102
12103 /*
12104  * The trap builtin.
12105  */
12106 static int
12107 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12108 {
12109         char *action;
12110         char **ap;
12111         int signo;
12112
12113         nextopt(nullstr);
12114         ap = argptr;
12115         if (!*ap) {
12116                 for (signo = 0; signo < NSIG; signo++) {
12117                         if (trap[signo] != NULL) {
12118                                 out1fmt("trap -- %s %s\n",
12119                                                 single_quote(trap[signo]),
12120                                                 get_signame(signo));
12121                         }
12122                 }
12123                 return 0;
12124         }
12125         action = NULL;
12126         if (ap[1])
12127                 action = *ap++;
12128         while (*ap) {
12129                 signo = get_signum(*ap);
12130                 if (signo < 0)
12131                         ash_msg_and_raise_error("%s: bad trap", *ap);
12132                 INT_OFF;
12133                 if (action) {
12134                         if (LONE_DASH(action))
12135                                 action = NULL;
12136                         else
12137                                 action = ckstrdup(action);
12138                 }
12139                 free(trap[signo]);
12140                 trap[signo] = action;
12141                 if (signo != 0)
12142                         setsignal(signo);
12143                 INT_ON;
12144                 ap++;
12145         }
12146         return 0;
12147 }
12148
12149
12150 /* ============ Builtins */
12151
12152 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12153 /*
12154  * Lists available builtins
12155  */
12156 static int
12157 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12158 {
12159         unsigned col;
12160         unsigned i;
12161
12162         out1fmt("\nBuilt-in commands:\n-------------------\n");
12163         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12164                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12165                                         builtintab[i].name + 1);
12166                 if (col > 60) {
12167                         out1fmt("\n");
12168                         col = 0;
12169                 }
12170         }
12171 #if ENABLE_FEATURE_SH_STANDALONE
12172         {
12173                 const char *a = applet_names;
12174                 while (*a) {
12175                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12176                         if (col > 60) {
12177                                 out1fmt("\n");
12178                                 col = 0;
12179                         }
12180                         a += strlen(a) + 1;
12181                 }
12182         }
12183 #endif
12184         out1fmt("\n\n");
12185         return EXIT_SUCCESS;
12186 }
12187 #endif /* FEATURE_SH_EXTRA_QUIET */
12188
12189 /*
12190  * The export and readonly commands.
12191  */
12192 static int
12193 exportcmd(int argc UNUSED_PARAM, char **argv)
12194 {
12195         struct var *vp;
12196         char *name;
12197         const char *p;
12198         char **aptr;
12199         int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12200
12201         if (nextopt("p") != 'p') {
12202                 aptr = argptr;
12203                 name = *aptr;
12204                 if (name) {
12205                         do {
12206                                 p = strchr(name, '=');
12207                                 if (p != NULL) {
12208                                         p++;
12209                                 } else {
12210                                         vp = *findvar(hashvar(name), name);
12211                                         if (vp) {
12212                                                 vp->flags |= flag;
12213                                                 continue;
12214                                         }
12215                                 }
12216                                 setvar(name, p, flag);
12217                         } while ((name = *++aptr) != NULL);
12218                         return 0;
12219                 }
12220         }
12221         showvars(argv[0], flag, 0);
12222         return 0;
12223 }
12224
12225 /*
12226  * Delete a function if it exists.
12227  */
12228 static void
12229 unsetfunc(const char *name)
12230 {
12231         struct tblentry *cmdp;
12232
12233         cmdp = cmdlookup(name, 0);
12234         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12235                 delete_cmd_entry();
12236 }
12237
12238 /*
12239  * The unset builtin command.  We unset the function before we unset the
12240  * variable to allow a function to be unset when there is a readonly variable
12241  * with the same name.
12242  */
12243 static int
12244 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12245 {
12246         char **ap;
12247         int i;
12248         int flag = 0;
12249         int ret = 0;
12250
12251         while ((i = nextopt("vf")) != '\0') {
12252                 flag = i;
12253         }
12254
12255         for (ap = argptr; *ap; ap++) {
12256                 if (flag != 'f') {
12257                         i = unsetvar(*ap);
12258                         ret |= i;
12259                         if (!(i & 2))
12260                                 continue;
12261                 }
12262                 if (flag != 'v')
12263                         unsetfunc(*ap);
12264         }
12265         return ret & 1;
12266 }
12267
12268
12269 /*      setmode.c      */
12270
12271 #include <sys/times.h>
12272
12273 static const unsigned char timescmd_str[] ALIGN1 = {
12274         ' ',  offsetof(struct tms, tms_utime),
12275         '\n', offsetof(struct tms, tms_stime),
12276         ' ',  offsetof(struct tms, tms_cutime),
12277         '\n', offsetof(struct tms, tms_cstime),
12278         0
12279 };
12280
12281 static int
12282 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12283 {
12284         long clk_tck, s, t;
12285         const unsigned char *p;
12286         struct tms buf;
12287
12288         clk_tck = sysconf(_SC_CLK_TCK);
12289         times(&buf);
12290
12291         p = timescmd_str;
12292         do {
12293                 t = *(clock_t *)(((char *) &buf) + p[1]);
12294                 s = t / clk_tck;
12295                 out1fmt("%ldm%ld.%.3lds%c",
12296                         s/60, s%60,
12297                         ((t - s * clk_tck) * 1000) / clk_tck,
12298                         p[0]);
12299         } while (*(p += 2));
12300
12301         return 0;
12302 }
12303
12304 #if ENABLE_ASH_MATH_SUPPORT
12305 static arith_t
12306 dash_arith(const char *s)
12307 {
12308         arith_t result;
12309         int errcode = 0;
12310
12311         INT_OFF;
12312         result = arith(s, &errcode);
12313         if (errcode < 0) {
12314                 if (errcode == -3)
12315                         ash_msg_and_raise_error("exponent less than 0");
12316                 if (errcode == -2)
12317                         ash_msg_and_raise_error("divide by zero");
12318                 if (errcode == -5)
12319                         ash_msg_and_raise_error("expression recursion loop detected");
12320                 raise_error_syntax(s);
12321         }
12322         INT_ON;
12323
12324         return result;
12325 }
12326
12327 /*
12328  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12329  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12330  *
12331  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12332  */
12333 static int
12334 letcmd(int argc UNUSED_PARAM, char **argv)
12335 {
12336         arith_t i;
12337
12338         argv++;
12339         if (!*argv)
12340                 ash_msg_and_raise_error("expression expected");
12341         do {
12342                 i = dash_arith(*argv);
12343         } while (*++argv);
12344
12345         return !i;
12346 }
12347 #endif /* ASH_MATH_SUPPORT */
12348
12349
12350 /* ============ miscbltin.c
12351  *
12352  * Miscellaneous builtins.
12353  */
12354
12355 #undef rflag
12356
12357 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12358 typedef enum __rlimit_resource rlim_t;
12359 #endif
12360
12361 /*
12362  * The read builtin. Options:
12363  *      -r              Do not interpret '\' specially
12364  *      -s              Turn off echo (tty only)
12365  *      -n NCHARS       Read NCHARS max
12366  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12367  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12368  *      -u FD           Read from given FD instead of fd 0
12369  * This uses unbuffered input, which may be avoidable in some cases.
12370  * TODO: bash also has:
12371  *      -a ARRAY        Read into array[0],[1],etc
12372  *      -d DELIM        End on DELIM char, not newline
12373  *      -e              Use line editing (tty only)
12374  */
12375 static int
12376 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12377 {
12378         static const char *const arg_REPLY[] = { "REPLY", NULL };
12379
12380         char **ap;
12381         int backslash;
12382         char c;
12383         int rflag;
12384         char *prompt;
12385         const char *ifs;
12386         char *p;
12387         int startword;
12388         int status;
12389         int i;
12390         int fd = 0;
12391 #if ENABLE_ASH_READ_NCHARS
12392         int nchars = 0; /* if != 0, -n is in effect */
12393         int silent = 0;
12394         struct termios tty, old_tty;
12395 #endif
12396 #if ENABLE_ASH_READ_TIMEOUT
12397         unsigned end_ms = 0;
12398         unsigned timeout = 0;
12399 #endif
12400
12401         rflag = 0;
12402         prompt = NULL;
12403         while ((i = nextopt("p:u:r"
12404                 USE_ASH_READ_TIMEOUT("t:")
12405                 USE_ASH_READ_NCHARS("n:s")
12406         )) != '\0') {
12407                 switch (i) {
12408                 case 'p':
12409                         prompt = optionarg;
12410                         break;
12411 #if ENABLE_ASH_READ_NCHARS
12412                 case 'n':
12413                         nchars = bb_strtou(optionarg, NULL, 10);
12414                         if (nchars < 0 || errno)
12415                                 ash_msg_and_raise_error("invalid count");
12416                         /* nchars == 0: off (bash 3.2 does this too) */
12417                         break;
12418                 case 's':
12419                         silent = 1;
12420                         break;
12421 #endif
12422 #if ENABLE_ASH_READ_TIMEOUT
12423                 case 't':
12424                         timeout = bb_strtou(optionarg, NULL, 10);
12425                         if (errno || timeout > UINT_MAX / 2048)
12426                                 ash_msg_and_raise_error("invalid timeout");
12427                         timeout *= 1000;
12428 #if 0 /* even bash have no -t N.NNN support */
12429                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
12430                         ts.tv_usec = 0;
12431                         /* EINVAL means number is ok, but not terminated by NUL */
12432                         if (*p == '.' && errno == EINVAL) {
12433                                 char *p2;
12434                                 if (*++p) {
12435                                         int scale;
12436                                         ts.tv_usec = bb_strtou(p, &p2, 10);
12437                                         if (errno)
12438                                                 ash_msg_and_raise_error("invalid timeout");
12439                                         scale = p2 - p;
12440                                         /* normalize to usec */
12441                                         if (scale > 6)
12442                                                 ash_msg_and_raise_error("invalid timeout");
12443                                         while (scale++ < 6)
12444                                                 ts.tv_usec *= 10;
12445                                 }
12446                         } else if (ts.tv_sec < 0 || errno) {
12447                                 ash_msg_and_raise_error("invalid timeout");
12448                         }
12449                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12450                                 ash_msg_and_raise_error("invalid timeout");
12451                         }
12452 #endif /* if 0 */
12453                         break;
12454 #endif
12455                 case 'r':
12456                         rflag = 1;
12457                         break;
12458                 case 'u':
12459                         fd = bb_strtou(optionarg, NULL, 10);
12460                         if (fd < 0 || errno)
12461                                 ash_msg_and_raise_error("invalid file descriptor");
12462                         break;
12463                 default:
12464                         break;
12465                 }
12466         }
12467         if (prompt && isatty(fd)) {
12468                 out2str(prompt);
12469         }
12470         ap = argptr;
12471         if (*ap == NULL)
12472                 ap = (char**)arg_REPLY;
12473         ifs = bltinlookup("IFS");
12474         if (ifs == NULL)
12475                 ifs = defifs;
12476 #if ENABLE_ASH_READ_NCHARS
12477         tcgetattr(fd, &tty);
12478         old_tty = tty;
12479         if (nchars || silent) {
12480                 if (nchars) {
12481                         tty.c_lflag &= ~ICANON;
12482                         tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12483                 }
12484                 if (silent) {
12485                         tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12486                 }
12487                 /* if tcgetattr failed, tcsetattr will fail too.
12488                  * Ignoring, it's harmless. */
12489                 tcsetattr(fd, TCSANOW, &tty);
12490         }
12491 #endif
12492
12493         status = 0;
12494         startword = 1;
12495         backslash = 0;
12496 #if ENABLE_ASH_READ_TIMEOUT
12497         if (timeout) /* NB: ensuring end_ms is nonzero */
12498                 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12499 #endif
12500         STARTSTACKSTR(p);
12501         do {
12502 #if ENABLE_ASH_READ_TIMEOUT
12503                 if (end_ms) {
12504                         struct pollfd pfd[1];
12505                         pfd[0].fd = fd;
12506                         pfd[0].events = POLLIN;
12507                         timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12508                         if ((int)timeout <= 0 /* already late? */
12509                          || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12510                         ) { /* timed out! */
12511 #if ENABLE_ASH_READ_NCHARS
12512                                 tcsetattr(fd, TCSANOW, &old_tty);
12513 #endif
12514                                 return 1;
12515                         }
12516                 }
12517 #endif
12518                 if (nonblock_safe_read(fd, &c, 1) != 1) {
12519                         status = 1;
12520                         break;
12521                 }
12522                 if (c == '\0')
12523                         continue;
12524                 if (backslash) {
12525                         backslash = 0;
12526                         if (c != '\n')
12527                                 goto put;
12528                         continue;
12529                 }
12530                 if (!rflag && c == '\\') {
12531                         backslash++;
12532                         continue;
12533                 }
12534                 if (c == '\n')
12535                         break;
12536                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12537                         continue;
12538                 }
12539                 startword = 0;
12540                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12541                         STACKSTRNUL(p);
12542                         setvar(*ap, stackblock(), 0);
12543                         ap++;
12544                         startword = 1;
12545                         STARTSTACKSTR(p);
12546                 } else {
12547  put:
12548                         STPUTC(c, p);
12549                 }
12550         }
12551 /* end of do {} while: */
12552 #if ENABLE_ASH_READ_NCHARS
12553         while (--nchars);
12554 #else
12555         while (1);
12556 #endif
12557
12558 #if ENABLE_ASH_READ_NCHARS
12559         tcsetattr(fd, TCSANOW, &old_tty);
12560 #endif
12561
12562         STACKSTRNUL(p);
12563         /* Remove trailing blanks */
12564         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12565                 *p = '\0';
12566         setvar(*ap, stackblock(), 0);
12567         while (*++ap != NULL)
12568                 setvar(*ap, nullstr, 0);
12569         return status;
12570 }
12571
12572 static int
12573 umaskcmd(int argc UNUSED_PARAM, char **argv)
12574 {
12575         static const char permuser[3] ALIGN1 = "ugo";
12576         static const char permmode[3] ALIGN1 = "rwx";
12577         static const short permmask[] ALIGN2 = {
12578                 S_IRUSR, S_IWUSR, S_IXUSR,
12579                 S_IRGRP, S_IWGRP, S_IXGRP,
12580                 S_IROTH, S_IWOTH, S_IXOTH
12581         };
12582
12583         char *ap;
12584         mode_t mask;
12585         int i;
12586         int symbolic_mode = 0;
12587
12588         while (nextopt("S") != '\0') {
12589                 symbolic_mode = 1;
12590         }
12591
12592         INT_OFF;
12593         mask = umask(0);
12594         umask(mask);
12595         INT_ON;
12596
12597         ap = *argptr;
12598         if (ap == NULL) {
12599                 if (symbolic_mode) {
12600                         char buf[18];
12601                         char *p = buf;
12602
12603                         for (i = 0; i < 3; i++) {
12604                                 int j;
12605
12606                                 *p++ = permuser[i];
12607                                 *p++ = '=';
12608                                 for (j = 0; j < 3; j++) {
12609                                         if ((mask & permmask[3 * i + j]) == 0) {
12610                                                 *p++ = permmode[j];
12611                                         }
12612                                 }
12613                                 *p++ = ',';
12614                         }
12615                         *--p = 0;
12616                         puts(buf);
12617                 } else {
12618                         out1fmt("%.4o\n", mask);
12619                 }
12620         } else {
12621                 if (isdigit((unsigned char) *ap)) {
12622                         mask = 0;
12623                         do {
12624                                 if (*ap >= '8' || *ap < '0')
12625                                         ash_msg_and_raise_error(illnum, argv[1]);
12626                                 mask = (mask << 3) + (*ap - '0');
12627                         } while (*++ap != '\0');
12628                         umask(mask);
12629                 } else {
12630                         mask = ~mask & 0777;
12631                         if (!bb_parse_mode(ap, &mask)) {
12632                                 ash_msg_and_raise_error("illegal mode: %s", ap);
12633                         }
12634                         umask(~mask & 0777);
12635                 }
12636         }
12637         return 0;
12638 }
12639
12640 /*
12641  * ulimit builtin
12642  *
12643  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12644  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12645  * ash by J.T. Conklin.
12646  *
12647  * Public domain.
12648  */
12649
12650 struct limits {
12651         uint8_t cmd;          /* RLIMIT_xxx fit into it */
12652         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12653         char    option;
12654 };
12655
12656 static const struct limits limits_tbl[] = {
12657 #ifdef RLIMIT_CPU
12658         { RLIMIT_CPU,        0, 't' },
12659 #endif
12660 #ifdef RLIMIT_FSIZE
12661         { RLIMIT_FSIZE,      9, 'f' },
12662 #endif
12663 #ifdef RLIMIT_DATA
12664         { RLIMIT_DATA,      10, 'd' },
12665 #endif
12666 #ifdef RLIMIT_STACK
12667         { RLIMIT_STACK,     10, 's' },
12668 #endif
12669 #ifdef RLIMIT_CORE
12670         { RLIMIT_CORE,       9, 'c' },
12671 #endif
12672 #ifdef RLIMIT_RSS
12673         { RLIMIT_RSS,       10, 'm' },
12674 #endif
12675 #ifdef RLIMIT_MEMLOCK
12676         { RLIMIT_MEMLOCK,   10, 'l' },
12677 #endif
12678 #ifdef RLIMIT_NPROC
12679         { RLIMIT_NPROC,      0, 'p' },
12680 #endif
12681 #ifdef RLIMIT_NOFILE
12682         { RLIMIT_NOFILE,     0, 'n' },
12683 #endif
12684 #ifdef RLIMIT_AS
12685         { RLIMIT_AS,        10, 'v' },
12686 #endif
12687 #ifdef RLIMIT_LOCKS
12688         { RLIMIT_LOCKS,      0, 'w' },
12689 #endif
12690 };
12691 static const char limits_name[] =
12692 #ifdef RLIMIT_CPU
12693         "time(seconds)" "\0"
12694 #endif
12695 #ifdef RLIMIT_FSIZE
12696         "file(blocks)" "\0"
12697 #endif
12698 #ifdef RLIMIT_DATA
12699         "data(kb)" "\0"
12700 #endif
12701 #ifdef RLIMIT_STACK
12702         "stack(kb)" "\0"
12703 #endif
12704 #ifdef RLIMIT_CORE
12705         "coredump(blocks)" "\0"
12706 #endif
12707 #ifdef RLIMIT_RSS
12708         "memory(kb)" "\0"
12709 #endif
12710 #ifdef RLIMIT_MEMLOCK
12711         "locked memory(kb)" "\0"
12712 #endif
12713 #ifdef RLIMIT_NPROC
12714         "process" "\0"
12715 #endif
12716 #ifdef RLIMIT_NOFILE
12717         "nofiles" "\0"
12718 #endif
12719 #ifdef RLIMIT_AS
12720         "vmemory(kb)" "\0"
12721 #endif
12722 #ifdef RLIMIT_LOCKS
12723         "locks" "\0"
12724 #endif
12725 ;
12726
12727 enum limtype { SOFT = 0x1, HARD = 0x2 };
12728
12729 static void
12730 printlim(enum limtype how, const struct rlimit *limit,
12731                         const struct limits *l)
12732 {
12733         rlim_t val;
12734
12735         val = limit->rlim_max;
12736         if (how & SOFT)
12737                 val = limit->rlim_cur;
12738
12739         if (val == RLIM_INFINITY)
12740                 out1fmt("unlimited\n");
12741         else {
12742                 val >>= l->factor_shift;
12743                 out1fmt("%lld\n", (long long) val);
12744         }
12745 }
12746
12747 static int
12748 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12749 {
12750         int c;
12751         rlim_t val = 0;
12752         enum limtype how = SOFT | HARD;
12753         const struct limits *l;
12754         int set, all = 0;
12755         int optc, what;
12756         struct rlimit limit;
12757
12758         what = 'f';
12759         while ((optc = nextopt("HSa"
12760 #ifdef RLIMIT_CPU
12761                                 "t"
12762 #endif
12763 #ifdef RLIMIT_FSIZE
12764                                 "f"
12765 #endif
12766 #ifdef RLIMIT_DATA
12767                                 "d"
12768 #endif
12769 #ifdef RLIMIT_STACK
12770                                 "s"
12771 #endif
12772 #ifdef RLIMIT_CORE
12773                                 "c"
12774 #endif
12775 #ifdef RLIMIT_RSS
12776                                 "m"
12777 #endif
12778 #ifdef RLIMIT_MEMLOCK
12779                                 "l"
12780 #endif
12781 #ifdef RLIMIT_NPROC
12782                                 "p"
12783 #endif
12784 #ifdef RLIMIT_NOFILE
12785                                 "n"
12786 #endif
12787 #ifdef RLIMIT_AS
12788                                 "v"
12789 #endif
12790 #ifdef RLIMIT_LOCKS
12791                                 "w"
12792 #endif
12793                                         )) != '\0')
12794                 switch (optc) {
12795                 case 'H':
12796                         how = HARD;
12797                         break;
12798                 case 'S':
12799                         how = SOFT;
12800                         break;
12801                 case 'a':
12802                         all = 1;
12803                         break;
12804                 default:
12805                         what = optc;
12806                 }
12807
12808         for (l = limits_tbl; l->option != what; l++)
12809                 continue;
12810
12811         set = *argptr ? 1 : 0;
12812         if (set) {
12813                 char *p = *argptr;
12814
12815                 if (all || argptr[1])
12816                         ash_msg_and_raise_error("too many arguments");
12817                 if (strncmp(p, "unlimited\n", 9) == 0)
12818                         val = RLIM_INFINITY;
12819                 else {
12820                         val = (rlim_t) 0;
12821
12822                         while ((c = *p++) >= '0' && c <= '9') {
12823                                 val = (val * 10) + (long)(c - '0');
12824                                 // val is actually 'unsigned long int' and can't get < 0
12825                                 if (val < (rlim_t) 0)
12826                                         break;
12827                         }
12828                         if (c)
12829                                 ash_msg_and_raise_error("bad number");
12830                         val <<= l->factor_shift;
12831                 }
12832         }
12833         if (all) {
12834                 const char *lname = limits_name;
12835                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12836                         getrlimit(l->cmd, &limit);
12837                         out1fmt("%-20s ", lname);
12838                         lname += strlen(lname) + 1;
12839                         printlim(how, &limit, l);
12840                 }
12841                 return 0;
12842         }
12843
12844         getrlimit(l->cmd, &limit);
12845         if (set) {
12846                 if (how & HARD)
12847                         limit.rlim_max = val;
12848                 if (how & SOFT)
12849                         limit.rlim_cur = val;
12850                 if (setrlimit(l->cmd, &limit) < 0)
12851                         ash_msg_and_raise_error("error setting limit (%m)");
12852         } else {
12853                 printlim(how, &limit, l);
12854         }
12855         return 0;
12856 }
12857
12858
12859 /* ============ Math support */
12860
12861 #if ENABLE_ASH_MATH_SUPPORT
12862
12863 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12864
12865    Permission is hereby granted, free of charge, to any person obtaining
12866    a copy of this software and associated documentation files (the
12867    "Software"), to deal in the Software without restriction, including
12868    without limitation the rights to use, copy, modify, merge, publish,
12869    distribute, sublicense, and/or sell copies of the Software, and to
12870    permit persons to whom the Software is furnished to do so, subject to
12871    the following conditions:
12872
12873    The above copyright notice and this permission notice shall be
12874    included in all copies or substantial portions of the Software.
12875
12876    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12877    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12878    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12879    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12880    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12881    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12882    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12883 */
12884
12885 /* This is my infix parser/evaluator. It is optimized for size, intended
12886  * as a replacement for yacc-based parsers. However, it may well be faster
12887  * than a comparable parser written in yacc. The supported operators are
12888  * listed in #defines below. Parens, order of operations, and error handling
12889  * are supported. This code is thread safe. The exact expression format should
12890  * be that which POSIX specifies for shells. */
12891
12892 /* The code uses a simple two-stack algorithm. See
12893  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12894  * for a detailed explanation of the infix-to-postfix algorithm on which
12895  * this is based (this code differs in that it applies operators immediately
12896  * to the stack instead of adding them to a queue to end up with an
12897  * expression). */
12898
12899 /* To use the routine, call it with an expression string and error return
12900  * pointer */
12901
12902 /*
12903  * Aug 24, 2001              Manuel Novoa III
12904  *
12905  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12906  *
12907  * 1) In arith_apply():
12908  *    a) Cached values of *numptr and &(numptr[-1]).
12909  *    b) Removed redundant test for zero denominator.
12910  *
12911  * 2) In arith():
12912  *    a) Eliminated redundant code for processing operator tokens by moving
12913  *       to a table-based implementation.  Also folded handling of parens
12914  *       into the table.
12915  *    b) Combined all 3 loops which called arith_apply to reduce generated
12916  *       code size at the cost of speed.
12917  *
12918  * 3) The following expressions were treated as valid by the original code:
12919  *       1()  ,    0!  ,    1 ( *3 )   .
12920  *    These bugs have been fixed by internally enclosing the expression in
12921  *    parens and then checking that all binary ops and right parens are
12922  *    preceded by a valid expression (NUM_TOKEN).
12923  *
12924  * Note: It may be desirable to replace Aaron's test for whitespace with
12925  * ctype's isspace() if it is used by another busybox applet or if additional
12926  * whitespace chars should be considered.  Look below the "#include"s for a
12927  * precompiler test.
12928  */
12929
12930 /*
12931  * Aug 26, 2001              Manuel Novoa III
12932  *
12933  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12934  *
12935  * Merge in Aaron's comments previously posted to the busybox list,
12936  * modified slightly to take account of my changes to the code.
12937  *
12938  */
12939
12940 /*
12941  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12942  *
12943  * - allow access to variable,
12944  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12945  * - realize assign syntax (VAR=expr, +=, *= etc)
12946  * - realize exponentiation (** operator)
12947  * - realize comma separated - expr, expr
12948  * - realise ++expr --expr expr++ expr--
12949  * - realise expr ? expr : expr (but, second expr calculate always)
12950  * - allow hexadecimal and octal numbers
12951  * - was restored loses XOR operator
12952  * - remove one goto label, added three ;-)
12953  * - protect $((num num)) as true zero expr (Manuel`s error)
12954  * - always use special isspace(), see comment from bash ;-)
12955  */
12956
12957 #define arith_isspace(arithval) \
12958         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12959
12960 typedef unsigned char operator;
12961
12962 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12963  * precedence, and 3 high bits are an ID unique across operators of that
12964  * precedence. The ID portion is so that multiple operators can have the
12965  * same precedence, ensuring that the leftmost one is evaluated first.
12966  * Consider * and /. */
12967
12968 #define tok_decl(prec,id) (((id)<<5)|(prec))
12969 #define PREC(op) ((op) & 0x1F)
12970
12971 #define TOK_LPAREN tok_decl(0,0)
12972
12973 #define TOK_COMMA tok_decl(1,0)
12974
12975 #define TOK_ASSIGN tok_decl(2,0)
12976 #define TOK_AND_ASSIGN tok_decl(2,1)
12977 #define TOK_OR_ASSIGN tok_decl(2,2)
12978 #define TOK_XOR_ASSIGN tok_decl(2,3)
12979 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12980 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12981 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12982 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12983
12984 #define TOK_MUL_ASSIGN tok_decl(3,0)
12985 #define TOK_DIV_ASSIGN tok_decl(3,1)
12986 #define TOK_REM_ASSIGN tok_decl(3,2)
12987
12988 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12989 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12990
12991 /* conditional is right associativity too */
12992 #define TOK_CONDITIONAL tok_decl(4,0)
12993 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12994
12995 #define TOK_OR tok_decl(5,0)
12996
12997 #define TOK_AND tok_decl(6,0)
12998
12999 #define TOK_BOR tok_decl(7,0)
13000
13001 #define TOK_BXOR tok_decl(8,0)
13002
13003 #define TOK_BAND tok_decl(9,0)
13004
13005 #define TOK_EQ tok_decl(10,0)
13006 #define TOK_NE tok_decl(10,1)
13007
13008 #define TOK_LT tok_decl(11,0)
13009 #define TOK_GT tok_decl(11,1)
13010 #define TOK_GE tok_decl(11,2)
13011 #define TOK_LE tok_decl(11,3)
13012
13013 #define TOK_LSHIFT tok_decl(12,0)
13014 #define TOK_RSHIFT tok_decl(12,1)
13015
13016 #define TOK_ADD tok_decl(13,0)
13017 #define TOK_SUB tok_decl(13,1)
13018
13019 #define TOK_MUL tok_decl(14,0)
13020 #define TOK_DIV tok_decl(14,1)
13021 #define TOK_REM tok_decl(14,2)
13022
13023 /* exponent is right associativity */
13024 #define TOK_EXPONENT tok_decl(15,1)
13025
13026 /* For now unary operators. */
13027 #define UNARYPREC 16
13028 #define TOK_BNOT tok_decl(UNARYPREC,0)
13029 #define TOK_NOT tok_decl(UNARYPREC,1)
13030
13031 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13032 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13033
13034 #define PREC_PRE (UNARYPREC+2)
13035
13036 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13037 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13038
13039 #define PREC_POST (UNARYPREC+3)
13040
13041 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13042 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13043
13044 #define SPEC_PREC (UNARYPREC+4)
13045
13046 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13047 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13048
13049 #define NUMPTR (*numstackptr)
13050
13051 static int
13052 tok_have_assign(operator op)
13053 {
13054         operator prec = PREC(op);
13055
13056         convert_prec_is_assing(prec);
13057         return (prec == PREC(TOK_ASSIGN) ||
13058                         prec == PREC_PRE || prec == PREC_POST);
13059 }
13060
13061 static int
13062 is_right_associativity(operator prec)
13063 {
13064         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13065                 || prec == PREC(TOK_CONDITIONAL));
13066 }
13067
13068 typedef struct {
13069         arith_t val;
13070         arith_t contidional_second_val;
13071         char contidional_second_val_initialized;
13072         char *var;      /* if NULL then is regular number,
13073                            else is variable name */
13074 } v_n_t;
13075
13076 typedef struct chk_var_recursive_looped_t {
13077         const char *var;
13078         struct chk_var_recursive_looped_t *next;
13079 } chk_var_recursive_looped_t;
13080
13081 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13082
13083 static int
13084 arith_lookup_val(v_n_t *t)
13085 {
13086         if (t->var) {
13087                 const char * p = lookupvar(t->var);
13088
13089                 if (p) {
13090                         int errcode;
13091
13092                         /* recursive try as expression */
13093                         chk_var_recursive_looped_t *cur;
13094                         chk_var_recursive_looped_t cur_save;
13095
13096                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13097                                 if (strcmp(cur->var, t->var) == 0) {
13098                                         /* expression recursion loop detected */
13099                                         return -5;
13100                                 }
13101                         }
13102                         /* save current lookuped var name */
13103                         cur = prev_chk_var_recursive;
13104                         cur_save.var = t->var;
13105                         cur_save.next = cur;
13106                         prev_chk_var_recursive = &cur_save;
13107
13108                         t->val = arith (p, &errcode);
13109                         /* restore previous ptr after recursiving */
13110                         prev_chk_var_recursive = cur;
13111                         return errcode;
13112                 }
13113                 /* allow undefined var as 0 */
13114                 t->val = 0;
13115         }
13116         return 0;
13117 }
13118
13119 /* "applying" a token means performing it on the top elements on the integer
13120  * stack. For a unary operator it will only change the top element, but a
13121  * binary operator will pop two arguments and push a result */
13122 static int
13123 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13124 {
13125         v_n_t *numptr_m1;
13126         arith_t numptr_val, rez;
13127         int ret_arith_lookup_val;
13128
13129         /* There is no operator that can work without arguments */
13130         if (NUMPTR == numstack) goto err;
13131         numptr_m1 = NUMPTR - 1;
13132
13133         /* check operand is var with noninteger value */
13134         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13135         if (ret_arith_lookup_val)
13136                 return ret_arith_lookup_val;
13137
13138         rez = numptr_m1->val;
13139         if (op == TOK_UMINUS)
13140                 rez *= -1;
13141         else if (op == TOK_NOT)
13142                 rez = !rez;
13143         else if (op == TOK_BNOT)
13144                 rez = ~rez;
13145         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13146                 rez++;
13147         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13148                 rez--;
13149         else if (op != TOK_UPLUS) {
13150                 /* Binary operators */
13151
13152                 /* check and binary operators need two arguments */
13153                 if (numptr_m1 == numstack) goto err;
13154
13155                 /* ... and they pop one */
13156                 --NUMPTR;
13157                 numptr_val = rez;
13158                 if (op == TOK_CONDITIONAL) {
13159                         if (!numptr_m1->contidional_second_val_initialized) {
13160                                 /* protect $((expr1 ? expr2)) without ": expr" */
13161                                 goto err;
13162                         }
13163                         rez = numptr_m1->contidional_second_val;
13164                 } else if (numptr_m1->contidional_second_val_initialized) {
13165                         /* protect $((expr1 : expr2)) without "expr ? " */
13166                         goto err;
13167                 }
13168                 numptr_m1 = NUMPTR - 1;
13169                 if (op != TOK_ASSIGN) {
13170                         /* check operand is var with noninteger value for not '=' */
13171                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13172                         if (ret_arith_lookup_val)
13173                                 return ret_arith_lookup_val;
13174                 }
13175                 if (op == TOK_CONDITIONAL) {
13176                         numptr_m1->contidional_second_val = rez;
13177                 }
13178                 rez = numptr_m1->val;
13179                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13180                         rez |= numptr_val;
13181                 else if (op == TOK_OR)
13182                         rez = numptr_val || rez;
13183                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13184                         rez &= numptr_val;
13185                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13186                         rez ^= numptr_val;
13187                 else if (op == TOK_AND)
13188                         rez = rez && numptr_val;
13189                 else if (op == TOK_EQ)
13190                         rez = (rez == numptr_val);
13191                 else if (op == TOK_NE)
13192                         rez = (rez != numptr_val);
13193                 else if (op == TOK_GE)
13194                         rez = (rez >= numptr_val);
13195                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13196                         rez >>= numptr_val;
13197                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13198                         rez <<= numptr_val;
13199                 else if (op == TOK_GT)
13200                         rez = (rez > numptr_val);
13201                 else if (op == TOK_LT)
13202                         rez = (rez < numptr_val);
13203                 else if (op == TOK_LE)
13204                         rez = (rez <= numptr_val);
13205                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13206                         rez *= numptr_val;
13207                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13208                         rez += numptr_val;
13209                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13210                         rez -= numptr_val;
13211                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13212                         rez = numptr_val;
13213                 else if (op == TOK_CONDITIONAL_SEP) {
13214                         if (numptr_m1 == numstack) {
13215                                 /* protect $((expr : expr)) without "expr ? " */
13216                                 goto err;
13217                         }
13218                         numptr_m1->contidional_second_val_initialized = op;
13219                         numptr_m1->contidional_second_val = numptr_val;
13220                 } else if (op == TOK_CONDITIONAL) {
13221                         rez = rez ?
13222                                 numptr_val : numptr_m1->contidional_second_val;
13223                 } else if (op == TOK_EXPONENT) {
13224                         if (numptr_val < 0)
13225                                 return -3;      /* exponent less than 0 */
13226                         else {
13227                                 arith_t c = 1;
13228
13229                                 if (numptr_val)
13230                                         while (numptr_val--)
13231                                                 c *= rez;
13232                                 rez = c;
13233                         }
13234                 } else if (numptr_val==0)          /* zero divisor check */
13235                         return -2;
13236                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13237                         rez /= numptr_val;
13238                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13239                         rez %= numptr_val;
13240         }
13241         if (tok_have_assign(op)) {
13242                 char buf[sizeof(arith_t_type)*3 + 2];
13243
13244                 if (numptr_m1->var == NULL) {
13245                         /* Hmm, 1=2 ? */
13246                         goto err;
13247                 }
13248                 /* save to shell variable */
13249 #if ENABLE_ASH_MATH_SUPPORT_64
13250                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13251 #else
13252                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13253 #endif
13254                 setvar(numptr_m1->var, buf, 0);
13255                 /* after saving, make previous value for v++ or v-- */
13256                 if (op == TOK_POST_INC)
13257                         rez--;
13258                 else if (op == TOK_POST_DEC)
13259                         rez++;
13260         }
13261         numptr_m1->val = rez;
13262         /* protect geting var value, is number now */
13263         numptr_m1->var = NULL;
13264         return 0;
13265  err:
13266         return -1;
13267 }
13268
13269 /* longest must be first */
13270 static const char op_tokens[] ALIGN1 = {
13271         '<','<','=',0, TOK_LSHIFT_ASSIGN,
13272         '>','>','=',0, TOK_RSHIFT_ASSIGN,
13273         '<','<',    0, TOK_LSHIFT,
13274         '>','>',    0, TOK_RSHIFT,
13275         '|','|',    0, TOK_OR,
13276         '&','&',    0, TOK_AND,
13277         '!','=',    0, TOK_NE,
13278         '<','=',    0, TOK_LE,
13279         '>','=',    0, TOK_GE,
13280         '=','=',    0, TOK_EQ,
13281         '|','=',    0, TOK_OR_ASSIGN,
13282         '&','=',    0, TOK_AND_ASSIGN,
13283         '*','=',    0, TOK_MUL_ASSIGN,
13284         '/','=',    0, TOK_DIV_ASSIGN,
13285         '%','=',    0, TOK_REM_ASSIGN,
13286         '+','=',    0, TOK_PLUS_ASSIGN,
13287         '-','=',    0, TOK_MINUS_ASSIGN,
13288         '-','-',    0, TOK_POST_DEC,
13289         '^','=',    0, TOK_XOR_ASSIGN,
13290         '+','+',    0, TOK_POST_INC,
13291         '*','*',    0, TOK_EXPONENT,
13292         '!',        0, TOK_NOT,
13293         '<',        0, TOK_LT,
13294         '>',        0, TOK_GT,
13295         '=',        0, TOK_ASSIGN,
13296         '|',        0, TOK_BOR,
13297         '&',        0, TOK_BAND,
13298         '*',        0, TOK_MUL,
13299         '/',        0, TOK_DIV,
13300         '%',        0, TOK_REM,
13301         '+',        0, TOK_ADD,
13302         '-',        0, TOK_SUB,
13303         '^',        0, TOK_BXOR,
13304         /* uniq */
13305         '~',        0, TOK_BNOT,
13306         ',',        0, TOK_COMMA,
13307         '?',        0, TOK_CONDITIONAL,
13308         ':',        0, TOK_CONDITIONAL_SEP,
13309         ')',        0, TOK_RPAREN,
13310         '(',        0, TOK_LPAREN,
13311         0
13312 };
13313 /* ptr to ")" */
13314 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13315
13316 static arith_t
13317 arith(const char *expr, int *perrcode)
13318 {
13319         char arithval; /* Current character under analysis */
13320         operator lasttok, op;
13321         operator prec;
13322         operator *stack, *stackptr;
13323         const char *p = endexpression;
13324         int errcode;
13325         v_n_t *numstack, *numstackptr;
13326         unsigned datasizes = strlen(expr) + 2;
13327
13328         /* Stack of integers */
13329         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13330          * in any given correct or incorrect expression is left as an exercise to
13331          * the reader. */
13332         numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13333         /* Stack of operator tokens */
13334         stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13335
13336         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
13337         *perrcode = errcode = 0;
13338
13339         while (1) {
13340                 arithval = *expr;
13341                 if (arithval == 0) {
13342                         if (p == endexpression) {
13343                                 /* Null expression. */
13344                                 return 0;
13345                         }
13346
13347                         /* This is only reached after all tokens have been extracted from the
13348                          * input stream. If there are still tokens on the operator stack, they
13349                          * are to be applied in order. At the end, there should be a final
13350                          * result on the integer stack */
13351
13352                         if (expr != endexpression + 1) {
13353                                 /* If we haven't done so already, */
13354                                 /* append a closing right paren */
13355                                 expr = endexpression;
13356                                 /* and let the loop process it. */
13357                                 continue;
13358                         }
13359                         /* At this point, we're done with the expression. */
13360                         if (numstackptr != numstack+1) {
13361                                 /* ... but if there isn't, it's bad */
13362  err:
13363                                 *perrcode = -1;
13364                                 return *perrcode;
13365                         }
13366                         if (numstack->var) {
13367                                 /* expression is $((var)) only, lookup now */
13368                                 errcode = arith_lookup_val(numstack);
13369                         }
13370  ret:
13371                         *perrcode = errcode;
13372                         return numstack->val;
13373                 }
13374
13375                 /* Continue processing the expression. */
13376                 if (arith_isspace(arithval)) {
13377                         /* Skip whitespace */
13378                         goto prologue;
13379                 }
13380                 p = endofname(expr);
13381                 if (p != expr) {
13382                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
13383
13384                         numstackptr->var = alloca(var_name_size);
13385                         safe_strncpy(numstackptr->var, expr, var_name_size);
13386                         expr = p;
13387  num:
13388                         numstackptr->contidional_second_val_initialized = 0;
13389                         numstackptr++;
13390                         lasttok = TOK_NUM;
13391                         continue;
13392                 }
13393                 if (isdigit(arithval)) {
13394                         numstackptr->var = NULL;
13395 #if ENABLE_ASH_MATH_SUPPORT_64
13396                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
13397 #else
13398                         numstackptr->val = strtol(expr, (char **) &expr, 0);
13399 #endif
13400                         goto num;
13401                 }
13402                 for (p = op_tokens; ; p++) {
13403                         const char *o;
13404
13405                         if (*p == 0) {
13406                                 /* strange operator not found */
13407                                 goto err;
13408                         }
13409                         for (o = expr; *p && *o == *p; p++)
13410                                 o++;
13411                         if (!*p) {
13412                                 /* found */
13413                                 expr = o - 1;
13414                                 break;
13415                         }
13416                         /* skip tail uncompared token */
13417                         while (*p)
13418                                 p++;
13419                         /* skip zero delim */
13420                         p++;
13421                 }
13422                 op = p[1];
13423
13424                 /* post grammar: a++ reduce to num */
13425                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13426                         lasttok = TOK_NUM;
13427
13428                 /* Plus and minus are binary (not unary) _only_ if the last
13429                  * token was as number, or a right paren (which pretends to be
13430                  * a number, since it evaluates to one). Think about it.
13431                  * It makes sense. */
13432                 if (lasttok != TOK_NUM) {
13433                         switch (op) {
13434                         case TOK_ADD:
13435                                 op = TOK_UPLUS;
13436                                 break;
13437                         case TOK_SUB:
13438                                 op = TOK_UMINUS;
13439                                 break;
13440                         case TOK_POST_INC:
13441                                 op = TOK_PRE_INC;
13442                                 break;
13443                         case TOK_POST_DEC:
13444                                 op = TOK_PRE_DEC;
13445                                 break;
13446                         }
13447                 }
13448                 /* We don't want a unary operator to cause recursive descent on the
13449                  * stack, because there can be many in a row and it could cause an
13450                  * operator to be evaluated before its argument is pushed onto the
13451                  * integer stack. */
13452                 /* But for binary operators, "apply" everything on the operator
13453                  * stack until we find an operator with a lesser priority than the
13454                  * one we have just extracted. */
13455                 /* Left paren is given the lowest priority so it will never be
13456                  * "applied" in this way.
13457                  * if associativity is right and priority eq, applied also skip
13458                  */
13459                 prec = PREC(op);
13460                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13461                         /* not left paren or unary */
13462                         if (lasttok != TOK_NUM) {
13463                                 /* binary op must be preceded by a num */
13464                                 goto err;
13465                         }
13466                         while (stackptr != stack) {
13467                                 if (op == TOK_RPAREN) {
13468                                         /* The algorithm employed here is simple: while we don't
13469                                          * hit an open paren nor the bottom of the stack, pop
13470                                          * tokens and apply them */
13471                                         if (stackptr[-1] == TOK_LPAREN) {
13472                                                 --stackptr;
13473                                                 /* Any operator directly after a */
13474                                                 lasttok = TOK_NUM;
13475                                                 /* close paren should consider itself binary */
13476                                                 goto prologue;
13477                                         }
13478                                 } else {
13479                                         operator prev_prec = PREC(stackptr[-1]);
13480
13481                                         convert_prec_is_assing(prec);
13482                                         convert_prec_is_assing(prev_prec);
13483                                         if (prev_prec < prec)
13484                                                 break;
13485                                         /* check right assoc */
13486                                         if (prev_prec == prec && is_right_associativity(prec))
13487                                                 break;
13488                                 }
13489                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13490                                 if (errcode) goto ret;
13491                         }
13492                         if (op == TOK_RPAREN) {
13493                                 goto err;
13494                         }
13495                 }
13496
13497                 /* Push this operator to the stack and remember it. */
13498                 *stackptr++ = lasttok = op;
13499  prologue:
13500                 ++expr;
13501         } /* while */
13502 }
13503 #endif /* ASH_MATH_SUPPORT */
13504
13505
13506 /* ============ main() and helpers */
13507
13508 /*
13509  * Called to exit the shell.
13510  */
13511 static void exitshell(void) NORETURN;
13512 static void
13513 exitshell(void)
13514 {
13515         struct jmploc loc;
13516         char *p;
13517         int status;
13518
13519         status = exitstatus;
13520         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13521         if (setjmp(loc.loc)) {
13522                 if (exception == EXEXIT)
13523 /* dash bug: it just does _exit(exitstatus) here
13524  * but we have to do setjobctl(0) first!
13525  * (bug is still not fixed in dash-0.5.3 - if you run dash
13526  * under Midnight Commander, on exit from dash MC is backgrounded) */
13527                         status = exitstatus;
13528                 goto out;
13529         }
13530         exception_handler = &loc;
13531         p = trap[0];
13532         if (p) {
13533                 trap[0] = NULL;
13534                 evalstring(p, 0);
13535         }
13536         flush_stdout_stderr();
13537  out:
13538         setjobctl(0);
13539         _exit(status);
13540         /* NOTREACHED */
13541 }
13542
13543 static void
13544 init(void)
13545 {
13546         /* from input.c: */
13547         basepf.next_to_pgetc = basepf.buf = basebuf;
13548
13549         /* from trap.c: */
13550         signal(SIGCHLD, SIG_DFL);
13551
13552         /* from var.c: */
13553         {
13554                 char **envp;
13555                 char ppid[sizeof(int)*3 + 1];
13556                 const char *p;
13557                 struct stat st1, st2;
13558
13559                 initvar();
13560                 for (envp = environ; envp && *envp; envp++) {
13561                         if (strchr(*envp, '=')) {
13562                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13563                         }
13564                 }
13565
13566                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13567                 setvar("PPID", ppid, 0);
13568
13569                 p = lookupvar("PWD");
13570                 if (p)
13571                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13572                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13573                                 p = '\0';
13574                 setpwd(p, 0);
13575         }
13576 }
13577
13578 /*
13579  * Process the shell command line arguments.
13580  */
13581 static void
13582 procargs(char **argv)
13583 {
13584         int i;
13585         const char *xminusc;
13586         char **xargv;
13587
13588         xargv = argv;
13589         arg0 = xargv[0];
13590         /* if (xargv[0]) - mmm, this is always true! */
13591                 xargv++;
13592         for (i = 0; i < NOPTS; i++)
13593                 optlist[i] = 2;
13594         argptr = xargv;
13595         if (options(1)) {
13596                 /* it already printed err message */
13597                 raise_exception(EXERROR);
13598         }
13599         xargv = argptr;
13600         xminusc = minusc;
13601         if (*xargv == NULL) {
13602                 if (xminusc)
13603                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13604                 sflag = 1;
13605         }
13606         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13607                 iflag = 1;
13608         if (mflag == 2)
13609                 mflag = iflag;
13610         for (i = 0; i < NOPTS; i++)
13611                 if (optlist[i] == 2)
13612                         optlist[i] = 0;
13613 #if DEBUG == 2
13614         debug = 1;
13615 #endif
13616         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13617         if (xminusc) {
13618                 minusc = *xargv++;
13619                 if (*xargv)
13620                         goto setarg0;
13621         } else if (!sflag) {
13622                 setinputfile(*xargv, 0);
13623  setarg0:
13624                 arg0 = *xargv++;
13625                 commandname = arg0;
13626         }
13627
13628         shellparam.p = xargv;
13629 #if ENABLE_ASH_GETOPTS
13630         shellparam.optind = 1;
13631         shellparam.optoff = -1;
13632 #endif
13633         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13634         while (*xargv) {
13635                 shellparam.nparam++;
13636                 xargv++;
13637         }
13638         optschanged();
13639 }
13640
13641 /*
13642  * Read /etc/profile or .profile.
13643  */
13644 static void
13645 read_profile(const char *name)
13646 {
13647         int skip;
13648
13649         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13650                 return;
13651         skip = cmdloop(0);
13652         popfile();
13653         if (skip)
13654                 exitshell();
13655 }
13656
13657 /*
13658  * This routine is called when an error or an interrupt occurs in an
13659  * interactive shell and control is returned to the main command loop.
13660  */
13661 static void
13662 reset(void)
13663 {
13664         /* from eval.c: */
13665         evalskip = 0;
13666         loopnest = 0;
13667         /* from input.c: */
13668         g_parsefile->left_in_buffer = 0;
13669         g_parsefile->left_in_line = 0;      /* clear input buffer */
13670         popallfiles();
13671         /* from parser.c: */
13672         tokpushback = 0;
13673         checkkwd = 0;
13674         /* from redir.c: */
13675         clearredir(/*drop:*/ 0);
13676 }
13677
13678 #if PROFILE
13679 static short profile_buf[16384];
13680 extern int etext();
13681 #endif
13682
13683 /*
13684  * Main routine.  We initialize things, parse the arguments, execute
13685  * profiles if we're a login shell, and then call cmdloop to execute
13686  * commands.  The setjmp call sets up the location to jump to when an
13687  * exception occurs.  When an exception occurs the variable "state"
13688  * is used to figure out how far we had gotten.
13689  */
13690 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13691 int ash_main(int argc UNUSED_PARAM, char **argv)
13692 {
13693         char *shinit;
13694         volatile int state;
13695         struct jmploc jmploc;
13696         struct stackmark smark;
13697
13698         /* Initialize global data */
13699         INIT_G_misc();
13700         INIT_G_memstack();
13701         INIT_G_var();
13702 #if ENABLE_ASH_ALIAS
13703         INIT_G_alias();
13704 #endif
13705         INIT_G_cmdtable();
13706
13707 #if PROFILE
13708         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13709 #endif
13710
13711 #if ENABLE_FEATURE_EDITING
13712         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13713 #endif
13714         state = 0;
13715         if (setjmp(jmploc.loc)) {
13716                 int e;
13717                 int s;
13718
13719                 reset();
13720
13721                 e = exception;
13722                 if (e == EXERROR)
13723                         exitstatus = 2;
13724                 s = state;
13725                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13726                         exitshell();
13727
13728                 if (e == EXINT) {
13729                         outcslow('\n', stderr);
13730                 }
13731                 popstackmark(&smark);
13732                 FORCE_INT_ON; /* enable interrupts */
13733                 if (s == 1)
13734                         goto state1;
13735                 if (s == 2)
13736                         goto state2;
13737                 if (s == 3)
13738                         goto state3;
13739                 goto state4;
13740         }
13741         exception_handler = &jmploc;
13742 #if DEBUG
13743         opentrace();
13744         trace_puts("Shell args: ");
13745         trace_puts_args(argv);
13746 #endif
13747         rootpid = getpid();
13748
13749 #if ENABLE_ASH_RANDOM_SUPPORT
13750         /* Can use monotonic_ns() for better randomness but for now it is
13751          * not used anywhere else in busybox... so avoid bloat */
13752         random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13753 #endif
13754         init();
13755         setstackmark(&smark);
13756         procargs(argv);
13757
13758 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13759         if (iflag) {
13760                 const char *hp = lookupvar("HISTFILE");
13761
13762                 if (hp == NULL) {
13763                         hp = lookupvar("HOME");
13764                         if (hp != NULL) {
13765                                 char *defhp = concat_path_file(hp, ".ash_history");
13766                                 setvar("HISTFILE", defhp, 0);
13767                                 free(defhp);
13768                         }
13769                 }
13770         }
13771 #endif
13772         if (argv[0] && argv[0][0] == '-')
13773                 isloginsh = 1;
13774         if (isloginsh) {
13775                 state = 1;
13776                 read_profile("/etc/profile");
13777  state1:
13778                 state = 2;
13779                 read_profile(".profile");
13780         }
13781  state2:
13782         state = 3;
13783         if (
13784 #ifndef linux
13785          getuid() == geteuid() && getgid() == getegid() &&
13786 #endif
13787          iflag
13788         ) {
13789                 shinit = lookupvar("ENV");
13790                 if (shinit != NULL && *shinit != '\0') {
13791                         read_profile(shinit);
13792                 }
13793         }
13794  state3:
13795         state = 4;
13796         if (minusc)
13797                 evalstring(minusc, 0);
13798
13799         if (sflag || minusc == NULL) {
13800 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13801                 if (iflag) {
13802                         const char *hp = lookupvar("HISTFILE");
13803
13804                         if (hp != NULL)
13805                                 line_input_state->hist_file = hp;
13806                 }
13807 #endif
13808  state4: /* XXX ??? - why isn't this before the "if" statement */
13809                 cmdloop(1);
13810         }
13811 #if PROFILE
13812         monitor(0);
13813 #endif
13814 #ifdef GPROF
13815         {
13816                 extern void _mcleanup(void);
13817                 _mcleanup();
13818         }
13819 #endif
13820         exitshell();
13821         /* NOTREACHED */
13822 }
13823
13824 #if DEBUG
13825 const char *applet_name = "debug stuff usage";
13826 int main(int argc, char **argv)
13827 {
13828         return ash_main(argc, argv);
13829 }
13830 #endif
13831
13832
13833 /*-
13834  * Copyright (c) 1989, 1991, 1993, 1994
13835  *      The Regents of the University of California.  All rights reserved.
13836  *
13837  * This code is derived from software contributed to Berkeley by
13838  * Kenneth Almquist.
13839  *
13840  * Redistribution and use in source and binary forms, with or without
13841  * modification, are permitted provided that the following conditions
13842  * are met:
13843  * 1. Redistributions of source code must retain the above copyright
13844  *    notice, this list of conditions and the following disclaimer.
13845  * 2. Redistributions in binary form must reproduce the above copyright
13846  *    notice, this list of conditions and the following disclaimer in the
13847  *    documentation and/or other materials provided with the distribution.
13848  * 3. Neither the name of the University nor the names of its contributors
13849  *    may be used to endorse or promote products derived from this software
13850  *    without specific prior written permission.
13851  *
13852  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13853  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13854  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13855  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13856  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13857  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13858  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13859  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13860  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13861  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13862  * SUCH DAMAGE.
13863  */