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