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