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