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