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