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