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