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