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