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