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