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