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