ash: fix comment, no code changes
[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 (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #endif
218 #if ENABLE_ASH_RANDOM_SUPPORT
219 # include "random.h"
220 #else
221 # define CLEAR_RANDOM_T(rnd) ((void)0)
222 #endif
223
224 #include "NUM_APPLETS.h"
225 #if NUM_APPLETS == 1
226 /* STANDALONE does not make sense, and won't compile */
227 # undef CONFIG_FEATURE_SH_STANDALONE
228 # undef ENABLE_FEATURE_SH_STANDALONE
229 # undef IF_FEATURE_SH_STANDALONE
230 # undef IF_NOT_FEATURE_SH_STANDALONE
231 # define ENABLE_FEATURE_SH_STANDALONE 0
232 # define IF_FEATURE_SH_STANDALONE(...)
233 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
234 #endif
235
236 #ifndef PIPE_BUF
237 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
238 #endif
239
240 #if !BB_MMU
241 # error "Do not even bother, ash will not run on NOMMU machine"
242 #endif
243
244
245 /* ============ Hash table sizes. Configurable. */
246
247 #define VTABSIZE 39
248 #define ATABSIZE 39
249 #define CMDTABLESIZE 31         /* should be prime */
250
251
252 /* ============ Shell options */
253
254 static const char *const optletters_optnames[] = {
255         "e"   "errexit",
256         "f"   "noglob",
257         "I"   "ignoreeof",
258         "i"   "interactive",
259         "m"   "monitor",
260         "n"   "noexec",
261         "s"   "stdin",
262         "x"   "xtrace",
263         "v"   "verbose",
264         "C"   "noclobber",
265         "a"   "allexport",
266         "b"   "notify",
267         "u"   "nounset",
268         "\0"  "vi"
269 #if BASH_PIPEFAIL
270         ,"\0"  "pipefail"
271 #endif
272 #if DEBUG
273         ,"\0"  "nolog"
274         ,"\0"  "debug"
275 #endif
276 };
277
278 #define optletters(n)  optletters_optnames[n][0]
279 #define optnames(n)   (optletters_optnames[n] + 1)
280
281 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
282
283
284 /* ============ Misc data */
285
286 #define msg_illnum "Illegal number: %s"
287
288 /*
289  * We enclose jmp_buf in a structure so that we can declare pointers to
290  * jump locations.  The global variable handler contains the location to
291  * jump to when an exception occurs, and the global variable exception_type
292  * contains a code identifying the exception.  To implement nested
293  * exception handlers, the user should save the value of handler on entry
294  * to an inner scope, set handler to point to a jmploc structure for the
295  * inner scope, and restore handler on exit from the scope.
296  */
297 struct jmploc {
298         jmp_buf loc;
299 };
300
301 struct globals_misc {
302         uint8_t exitstatus;     /* exit status of last command */
303         uint8_t back_exitstatus;/* exit status of backquoted command */
304         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
305         int rootpid;            /* pid of main shell */
306         /* shell level: 0 for the main shell, 1 for its children, and so on */
307         int shlvl;
308 #define rootshell (!shlvl)
309         char *minusc;  /* argument to -c option */
310
311         char *curdir; // = nullstr;     /* current working directory */
312         char *physdir; // = nullstr;    /* physical working directory */
313
314         char *arg0; /* value of $0 */
315
316         struct jmploc *exception_handler;
317
318         volatile int suppress_int; /* counter */
319         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
320         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
321         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
322         smallint exception_type; /* kind of exception (0..5) */
323         /* exceptions */
324 #define EXINT 0         /* SIGINT received */
325 #define EXERROR 1       /* a generic error */
326 #define EXEXIT 4        /* exit the shell */
327
328         smallint isloginsh;
329         char nullstr[1];        /* zero length string */
330
331         char optlist[NOPTS];
332 #define eflag optlist[0]
333 #define fflag optlist[1]
334 #define Iflag optlist[2]
335 #define iflag optlist[3]
336 #define mflag optlist[4]
337 #define nflag optlist[5]
338 #define sflag optlist[6]
339 #define xflag optlist[7]
340 #define vflag optlist[8]
341 #define Cflag optlist[9]
342 #define aflag optlist[10]
343 #define bflag optlist[11]
344 #define uflag optlist[12]
345 #define viflag optlist[13]
346 #if BASH_PIPEFAIL
347 # define pipefail optlist[14]
348 #else
349 # define pipefail 0
350 #endif
351 #if DEBUG
352 # define nolog optlist[14 + BASH_PIPEFAIL]
353 # define debug optlist[15 + BASH_PIPEFAIL]
354 #endif
355
356         /* trap handler commands */
357         /*
358          * Sigmode records the current value of the signal handlers for the various
359          * modes.  A value of zero means that the current handler is not known.
360          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
361          */
362         char sigmode[NSIG - 1];
363 #define S_DFL      1            /* default signal handling (SIG_DFL) */
364 #define S_CATCH    2            /* signal is caught */
365 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
366 #define S_HARD_IGN 4            /* signal is ignored permanently */
367
368         /* indicates specified signal received */
369         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
370         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
371         char *trap[NSIG];
372         char **trap_ptr;        /* used only by "trap hack" */
373
374         /* Rarely referenced stuff */
375 #if ENABLE_ASH_RANDOM_SUPPORT
376         random_t random_gen;
377 #endif
378         pid_t backgndpid;        /* pid of last background process */
379 };
380 extern struct globals_misc *const ash_ptr_to_globals_misc;
381 #define G_misc (*ash_ptr_to_globals_misc)
382 #define exitstatus        (G_misc.exitstatus )
383 #define back_exitstatus   (G_misc.back_exitstatus )
384 #define job_warning       (G_misc.job_warning)
385 #define rootpid     (G_misc.rootpid    )
386 #define shlvl       (G_misc.shlvl      )
387 #define minusc      (G_misc.minusc     )
388 #define curdir      (G_misc.curdir     )
389 #define physdir     (G_misc.physdir    )
390 #define arg0        (G_misc.arg0       )
391 #define exception_handler (G_misc.exception_handler)
392 #define exception_type    (G_misc.exception_type   )
393 #define suppress_int      (G_misc.suppress_int     )
394 #define pending_int       (G_misc.pending_int      )
395 #define got_sigchld       (G_misc.got_sigchld      )
396 #define pending_sig       (G_misc.pending_sig      )
397 #define isloginsh   (G_misc.isloginsh  )
398 #define nullstr     (G_misc.nullstr    )
399 #define optlist     (G_misc.optlist    )
400 #define sigmode     (G_misc.sigmode    )
401 #define gotsig      (G_misc.gotsig     )
402 #define may_have_traps    (G_misc.may_have_traps   )
403 #define trap        (G_misc.trap       )
404 #define trap_ptr    (G_misc.trap_ptr   )
405 #define random_gen  (G_misc.random_gen )
406 #define backgndpid  (G_misc.backgndpid )
407 #define INIT_G_misc() do { \
408         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
409         barrier(); \
410         curdir = nullstr; \
411         physdir = nullstr; \
412         trap_ptr = trap; \
413 } while (0)
414
415
416 /* ============ DEBUG */
417 #if DEBUG
418 static void trace_printf(const char *fmt, ...);
419 static void trace_vprintf(const char *fmt, va_list va);
420 # define TRACE(param)    trace_printf param
421 # define TRACEV(param)   trace_vprintf param
422 # define close(fd) do { \
423         int dfd = (fd); \
424         if (close(dfd) < 0) \
425                 bb_error_msg("bug on %d: closing %d(0x%x)", \
426                         __LINE__, dfd, dfd); \
427 } while (0)
428 #else
429 # define TRACE(param)
430 # define TRACEV(param)
431 #endif
432
433
434 /* ============ Utility functions */
435 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
436 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
437
438 static int
439 isdigit_str9(const char *str)
440 {
441         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
442         while (--maxlen && isdigit(*str))
443                 str++;
444         return (*str == '\0');
445 }
446
447 static const char *
448 var_end(const char *var)
449 {
450         while (*var)
451                 if (*var++ == '=')
452                         break;
453         return var;
454 }
455
456
457 /* ============ Interrupts / exceptions */
458
459 static void exitshell(void) NORETURN;
460
461 /*
462  * These macros allow the user to suspend the handling of interrupt signals
463  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
464  * much more efficient and portable.  (But hacking the kernel is so much
465  * more fun than worrying about efficiency and portability. :-))
466  */
467 #if DEBUG_INTONOFF
468 # define INT_OFF do { \
469         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
470         suppress_int++; \
471         barrier(); \
472 } while (0)
473 #else
474 # define INT_OFF do { \
475         suppress_int++; \
476         barrier(); \
477 } while (0)
478 #endif
479
480 /*
481  * Called to raise an exception.  Since C doesn't include exceptions, we
482  * just do a longjmp to the exception handler.  The type of exception is
483  * stored in the global variable "exception_type".
484  */
485 static void raise_exception(int) NORETURN;
486 static void
487 raise_exception(int e)
488 {
489 #if DEBUG
490         if (exception_handler == NULL)
491                 abort();
492 #endif
493         INT_OFF;
494         exception_type = e;
495         longjmp(exception_handler->loc, 1);
496 }
497 #if DEBUG
498 #define raise_exception(e) do { \
499         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
500         raise_exception(e); \
501 } while (0)
502 #endif
503
504 /*
505  * Called when a SIGINT is received.  (If the user specifies
506  * that SIGINT is to be trapped or ignored using the trap builtin, then
507  * this routine is not called.)  Suppressint is nonzero when interrupts
508  * are held using the INT_OFF macro.  (The test for iflag is just
509  * defensive programming.)
510  */
511 static void raise_interrupt(void) NORETURN;
512 static void
513 raise_interrupt(void)
514 {
515         pending_int = 0;
516         /* Signal is not automatically unmasked after it is raised,
517          * do it ourself - unmask all signals */
518         sigprocmask_allsigs(SIG_UNBLOCK);
519         /* pending_sig = 0; - now done in signal_handler() */
520
521         if (!(rootshell && iflag)) {
522                 /* Kill ourself with SIGINT */
523                 signal(SIGINT, SIG_DFL);
524                 raise(SIGINT);
525         }
526         /* bash: ^C even on empty command line sets $? */
527         exitstatus = SIGINT + 128;
528         raise_exception(EXINT);
529         /* NOTREACHED */
530 }
531 #if DEBUG
532 #define raise_interrupt() do { \
533         TRACE(("raising interrupt on line %d\n", __LINE__)); \
534         raise_interrupt(); \
535 } while (0)
536 #endif
537
538 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
539 int_on(void)
540 {
541         barrier();
542         if (--suppress_int == 0 && pending_int) {
543                 raise_interrupt();
544         }
545 }
546 #if DEBUG_INTONOFF
547 # define INT_ON do { \
548         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
549         int_on(); \
550 } while (0)
551 #else
552 # define INT_ON int_on()
553 #endif
554 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
555 force_int_on(void)
556 {
557         barrier();
558         suppress_int = 0;
559         if (pending_int)
560                 raise_interrupt();
561 }
562 #define FORCE_INT_ON force_int_on()
563
564 #define SAVE_INT(v) ((v) = suppress_int)
565
566 #define RESTORE_INT(v) do { \
567         barrier(); \
568         suppress_int = (v); \
569         if (suppress_int == 0 && pending_int) \
570                 raise_interrupt(); \
571 } while (0)
572
573
574 /* ============ Stdout/stderr output */
575
576 static void
577 outstr(const char *p, FILE *file)
578 {
579         INT_OFF;
580         fputs(p, file);
581         INT_ON;
582 }
583
584 static void
585 flush_stdout_stderr(void)
586 {
587         INT_OFF;
588         fflush_all();
589         INT_ON;
590 }
591
592 /* Was called outcslow(c,FILE*), but c was always '\n' */
593 static void
594 newline_and_flush(FILE *dest)
595 {
596         INT_OFF;
597         putc('\n', dest);
598         fflush(dest);
599         INT_ON;
600 }
601
602 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
603 static int
604 out1fmt(const char *fmt, ...)
605 {
606         va_list ap;
607         int r;
608
609         INT_OFF;
610         va_start(ap, fmt);
611         r = vprintf(fmt, ap);
612         va_end(ap);
613         INT_ON;
614         return r;
615 }
616
617 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
618 static int
619 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
620 {
621         va_list ap;
622         int ret;
623
624         va_start(ap, fmt);
625         INT_OFF;
626         ret = vsnprintf(outbuf, length, fmt, ap);
627         va_end(ap);
628         INT_ON;
629         return ret;
630 }
631
632 static void
633 out1str(const char *p)
634 {
635         outstr(p, stdout);
636 }
637
638 static void
639 out2str(const char *p)
640 {
641         outstr(p, stderr);
642         flush_stdout_stderr();
643 }
644
645
646 /* ============ Parser structures */
647
648 /* control characters in argument strings */
649 #define CTL_FIRST CTLESC
650 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
651 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
652 #define CTLENDVAR    ((unsigned char)'\203')
653 #define CTLBACKQ     ((unsigned char)'\204')
654 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
655 #define CTLENDARI    ((unsigned char)'\207')
656 #define CTLQUOTEMARK ((unsigned char)'\210')
657 #define CTL_LAST CTLQUOTEMARK
658
659 /* variable substitution byte (follows CTLVAR) */
660 #define VSTYPE  0x0f            /* type of variable substitution */
661 #define VSNUL   0x10            /* colon--treat the empty string as unset */
662
663 /* values of VSTYPE field */
664 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
665 #define VSMINUS         0x2     /* ${var-text} */
666 #define VSPLUS          0x3     /* ${var+text} */
667 #define VSQUESTION      0x4     /* ${var?message} */
668 #define VSASSIGN        0x5     /* ${var=text} */
669 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
670 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
671 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
672 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
673 #define VSLENGTH        0xa     /* ${#var} */
674 #if BASH_SUBSTR
675 #define VSSUBSTR        0xc     /* ${var:position:length} */
676 #endif
677 #if BASH_PATTERN_SUBST
678 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
679 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
680 #endif
681
682 static const char dolatstr[] ALIGN1 = {
683         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
684 };
685 #define DOLATSTRLEN 6
686
687 #define NCMD      0
688 #define NPIPE     1
689 #define NREDIR    2
690 #define NBACKGND  3
691 #define NSUBSHELL 4
692 #define NAND      5
693 #define NOR       6
694 #define NSEMI     7
695 #define NIF       8
696 #define NWHILE    9
697 #define NUNTIL   10
698 #define NFOR     11
699 #define NCASE    12
700 #define NCLIST   13
701 #define NDEFUN   14
702 #define NARG     15
703 #define NTO      16
704 #if BASH_REDIR_OUTPUT
705 #define NTO2     17
706 #endif
707 #define NCLOBBER 18
708 #define NFROM    19
709 #define NFROMTO  20
710 #define NAPPEND  21
711 #define NTOFD    22
712 #define NFROMFD  23
713 #define NHERE    24
714 #define NXHERE   25
715 #define NNOT     26
716 #define N_NUMBER 27
717
718 union node;
719
720 struct ncmd {
721         smallint type; /* Nxxxx */
722         union node *assign;
723         union node *args;
724         union node *redirect;
725 };
726
727 struct npipe {
728         smallint type;
729         smallint pipe_backgnd;
730         struct nodelist *cmdlist;
731 };
732
733 struct nredir {
734         smallint type;
735         union node *n;
736         union node *redirect;
737 };
738
739 struct nbinary {
740         smallint type;
741         union node *ch1;
742         union node *ch2;
743 };
744
745 struct nif {
746         smallint type;
747         union node *test;
748         union node *ifpart;
749         union node *elsepart;
750 };
751
752 struct nfor {
753         smallint type;
754         union node *args;
755         union node *body;
756         char *var;
757 };
758
759 struct ncase {
760         smallint type;
761         union node *expr;
762         union node *cases;
763 };
764
765 struct nclist {
766         smallint type;
767         union node *next;
768         union node *pattern;
769         union node *body;
770 };
771
772 struct narg {
773         smallint type;
774         union node *next;
775         char *text;
776         struct nodelist *backquote;
777 };
778
779 /* nfile and ndup layout must match!
780  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
781  * that it is actually NTO2 (>&file), and change its type.
782  */
783 struct nfile {
784         smallint type;
785         union node *next;
786         int fd;
787         int _unused_dupfd;
788         union node *fname;
789         char *expfname;
790 };
791
792 struct ndup {
793         smallint type;
794         union node *next;
795         int fd;
796         int dupfd;
797         union node *vname;
798         char *_unused_expfname;
799 };
800
801 struct nhere {
802         smallint type;
803         union node *next;
804         int fd;
805         union node *doc;
806 };
807
808 struct nnot {
809         smallint type;
810         union node *com;
811 };
812
813 union node {
814         smallint type;
815         struct ncmd ncmd;
816         struct npipe npipe;
817         struct nredir nredir;
818         struct nbinary nbinary;
819         struct nif nif;
820         struct nfor nfor;
821         struct ncase ncase;
822         struct nclist nclist;
823         struct narg narg;
824         struct nfile nfile;
825         struct ndup ndup;
826         struct nhere nhere;
827         struct nnot nnot;
828 };
829
830 /*
831  * NODE_EOF is returned by parsecmd when it encounters an end of file.
832  * It must be distinct from NULL.
833  */
834 #define NODE_EOF ((union node *) -1L)
835
836 struct nodelist {
837         struct nodelist *next;
838         union node *n;
839 };
840
841 struct funcnode {
842         int count;
843         union node n;
844 };
845
846 /*
847  * Free a parse tree.
848  */
849 static void
850 freefunc(struct funcnode *f)
851 {
852         if (f && --f->count < 0)
853                 free(f);
854 }
855
856
857 /* ============ Debugging output */
858
859 #if DEBUG
860
861 static FILE *tracefile;
862
863 static void
864 trace_printf(const char *fmt, ...)
865 {
866         va_list va;
867
868         if (debug != 1)
869                 return;
870         if (DEBUG_TIME)
871                 fprintf(tracefile, "%u ", (int) time(NULL));
872         if (DEBUG_PID)
873                 fprintf(tracefile, "[%u] ", (int) getpid());
874         if (DEBUG_SIG)
875                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
876         va_start(va, fmt);
877         vfprintf(tracefile, fmt, va);
878         va_end(va);
879 }
880
881 static void
882 trace_vprintf(const char *fmt, va_list va)
883 {
884         if (debug != 1)
885                 return;
886         vfprintf(tracefile, fmt, va);
887         fprintf(tracefile, "\n");
888 }
889
890 static void
891 trace_puts(const char *s)
892 {
893         if (debug != 1)
894                 return;
895         fputs(s, tracefile);
896 }
897
898 static void
899 trace_puts_quoted(char *s)
900 {
901         char *p;
902         char c;
903
904         if (debug != 1)
905                 return;
906         putc('"', tracefile);
907         for (p = s; *p; p++) {
908                 switch ((unsigned char)*p) {
909                 case '\n': c = 'n'; goto backslash;
910                 case '\t': c = 't'; goto backslash;
911                 case '\r': c = 'r'; goto backslash;
912                 case '\"': c = '\"'; goto backslash;
913                 case '\\': c = '\\'; goto backslash;
914                 case CTLESC: c = 'e'; goto backslash;
915                 case CTLVAR: c = 'v'; goto backslash;
916                 case CTLBACKQ: c = 'q'; goto backslash;
917  backslash:
918                         putc('\\', tracefile);
919                         putc(c, tracefile);
920                         break;
921                 default:
922                         if (*p >= ' ' && *p <= '~')
923                                 putc(*p, tracefile);
924                         else {
925                                 putc('\\', tracefile);
926                                 putc((*p >> 6) & 03, tracefile);
927                                 putc((*p >> 3) & 07, tracefile);
928                                 putc(*p & 07, tracefile);
929                         }
930                         break;
931                 }
932         }
933         putc('"', tracefile);
934 }
935
936 static void
937 trace_puts_args(char **ap)
938 {
939         if (debug != 1)
940                 return;
941         if (!*ap)
942                 return;
943         while (1) {
944                 trace_puts_quoted(*ap);
945                 if (!*++ap) {
946                         putc('\n', tracefile);
947                         break;
948                 }
949                 putc(' ', tracefile);
950         }
951 }
952
953 static void
954 opentrace(void)
955 {
956         char s[100];
957 #ifdef O_APPEND
958         int flags;
959 #endif
960
961         if (debug != 1) {
962                 if (tracefile)
963                         fflush(tracefile);
964                 /* leave open because libedit might be using it */
965                 return;
966         }
967         strcpy(s, "./trace");
968         if (tracefile) {
969                 if (!freopen(s, "a", tracefile)) {
970                         fprintf(stderr, "Can't re-open %s\n", s);
971                         debug = 0;
972                         return;
973                 }
974         } else {
975                 tracefile = fopen(s, "a");
976                 if (tracefile == NULL) {
977                         fprintf(stderr, "Can't open %s\n", s);
978                         debug = 0;
979                         return;
980                 }
981         }
982 #ifdef O_APPEND
983         flags = fcntl(fileno(tracefile), F_GETFL);
984         if (flags >= 0)
985                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
986 #endif
987         setlinebuf(tracefile);
988         fputs("\nTracing started.\n", tracefile);
989 }
990
991 static void
992 indent(int amount, char *pfx, FILE *fp)
993 {
994         int i;
995
996         for (i = 0; i < amount; i++) {
997                 if (pfx && i == amount - 1)
998                         fputs(pfx, fp);
999                 putc('\t', fp);
1000         }
1001 }
1002
1003 /* little circular references here... */
1004 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1005
1006 static void
1007 sharg(union node *arg, FILE *fp)
1008 {
1009         char *p;
1010         struct nodelist *bqlist;
1011         unsigned char subtype;
1012
1013         if (arg->type != NARG) {
1014                 out1fmt("<node type %d>\n", arg->type);
1015                 abort();
1016         }
1017         bqlist = arg->narg.backquote;
1018         for (p = arg->narg.text; *p; p++) {
1019                 switch ((unsigned char)*p) {
1020                 case CTLESC:
1021                         p++;
1022                         putc(*p, fp);
1023                         break;
1024                 case CTLVAR:
1025                         putc('$', fp);
1026                         putc('{', fp);
1027                         subtype = *++p;
1028                         if (subtype == VSLENGTH)
1029                                 putc('#', fp);
1030
1031                         while (*p != '=') {
1032                                 putc(*p, fp);
1033                                 p++;
1034                         }
1035
1036                         if (subtype & VSNUL)
1037                                 putc(':', fp);
1038
1039                         switch (subtype & VSTYPE) {
1040                         case VSNORMAL:
1041                                 putc('}', fp);
1042                                 break;
1043                         case VSMINUS:
1044                                 putc('-', fp);
1045                                 break;
1046                         case VSPLUS:
1047                                 putc('+', fp);
1048                                 break;
1049                         case VSQUESTION:
1050                                 putc('?', fp);
1051                                 break;
1052                         case VSASSIGN:
1053                                 putc('=', fp);
1054                                 break;
1055                         case VSTRIMLEFT:
1056                                 putc('#', fp);
1057                                 break;
1058                         case VSTRIMLEFTMAX:
1059                                 putc('#', fp);
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMRIGHT:
1063                                 putc('%', fp);
1064                                 break;
1065                         case VSTRIMRIGHTMAX:
1066                                 putc('%', fp);
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSLENGTH:
1070                                 break;
1071                         default:
1072                                 out1fmt("<subtype %d>", subtype);
1073                         }
1074                         break;
1075                 case CTLENDVAR:
1076                         putc('}', fp);
1077                         break;
1078                 case CTLBACKQ:
1079                         putc('$', fp);
1080                         putc('(', fp);
1081                         shtree(bqlist->n, -1, NULL, fp);
1082                         putc(')', fp);
1083                         break;
1084                 default:
1085                         putc(*p, fp);
1086                         break;
1087                 }
1088         }
1089 }
1090
1091 static void
1092 shcmd(union node *cmd, FILE *fp)
1093 {
1094         union node *np;
1095         int first;
1096         const char *s;
1097         int dftfd;
1098
1099         first = 1;
1100         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1101                 if (!first)
1102                         putc(' ', fp);
1103                 sharg(np, fp);
1104                 first = 0;
1105         }
1106         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1107                 if (!first)
1108                         putc(' ', fp);
1109                 dftfd = 0;
1110                 switch (np->nfile.type) {
1111                 case NTO:      s = ">>"+1; dftfd = 1; break;
1112                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1113                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1114 #if BASH_REDIR_OUTPUT
1115                 case NTO2:
1116 #endif
1117                 case NTOFD:    s = ">&"; dftfd = 1; break;
1118                 case NFROM:    s = "<"; break;
1119                 case NFROMFD:  s = "<&"; break;
1120                 case NFROMTO:  s = "<>"; break;
1121                 default:       s = "*error*"; break;
1122                 }
1123                 if (np->nfile.fd != dftfd)
1124                         fprintf(fp, "%d", np->nfile.fd);
1125                 fputs(s, fp);
1126                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1127                         fprintf(fp, "%d", np->ndup.dupfd);
1128                 } else {
1129                         sharg(np->nfile.fname, fp);
1130                 }
1131                 first = 0;
1132         }
1133 }
1134
1135 static void
1136 shtree(union node *n, int ind, char *pfx, FILE *fp)
1137 {
1138         struct nodelist *lp;
1139         const char *s;
1140
1141         if (n == NULL)
1142                 return;
1143
1144         indent(ind, pfx, fp);
1145
1146         if (n == NODE_EOF) {
1147                 fputs("<EOF>", fp);
1148                 return;
1149         }
1150
1151         switch (n->type) {
1152         case NSEMI:
1153                 s = "; ";
1154                 goto binop;
1155         case NAND:
1156                 s = " && ";
1157                 goto binop;
1158         case NOR:
1159                 s = " || ";
1160  binop:
1161                 shtree(n->nbinary.ch1, ind, NULL, fp);
1162                 /* if (ind < 0) */
1163                         fputs(s, fp);
1164                 shtree(n->nbinary.ch2, ind, NULL, fp);
1165                 break;
1166         case NCMD:
1167                 shcmd(n, fp);
1168                 if (ind >= 0)
1169                         putc('\n', fp);
1170                 break;
1171         case NPIPE:
1172                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1173                         shtree(lp->n, 0, NULL, fp);
1174                         if (lp->next)
1175                                 fputs(" | ", fp);
1176                 }
1177                 if (n->npipe.pipe_backgnd)
1178                         fputs(" &", fp);
1179                 if (ind >= 0)
1180                         putc('\n', fp);
1181                 break;
1182         default:
1183                 fprintf(fp, "<node type %d>", n->type);
1184                 if (ind >= 0)
1185                         putc('\n', fp);
1186                 break;
1187         }
1188 }
1189
1190 static void
1191 showtree(union node *n)
1192 {
1193         trace_puts("showtree called\n");
1194         shtree(n, 1, NULL, stderr);
1195 }
1196
1197 #endif /* DEBUG */
1198
1199
1200 /* ============ Parser data */
1201
1202 /*
1203  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1204  */
1205 struct strlist {
1206         struct strlist *next;
1207         char *text;
1208 };
1209
1210 struct alias;
1211
1212 struct strpush {
1213         struct strpush *prev;   /* preceding string on stack */
1214         char *prev_string;
1215         int prev_left_in_line;
1216 #if ENABLE_ASH_ALIAS
1217         struct alias *ap;       /* if push was associated with an alias */
1218 #endif
1219         char *string;           /* remember the string since it may change */
1220
1221         /* Remember last two characters for pungetc. */
1222         int lastc[2];
1223
1224         /* Number of outstanding calls to pungetc. */
1225         int unget;
1226 };
1227
1228 struct parsefile {
1229         struct parsefile *prev; /* preceding file on stack */
1230         int linno;              /* current line */
1231         int pf_fd;              /* file descriptor (or -1 if string) */
1232         int left_in_line;       /* number of chars left in this line */
1233         int left_in_buffer;     /* number of chars left in this buffer past the line */
1234         char *next_to_pgetc;    /* next char in buffer */
1235         char *buf;              /* input buffer */
1236         struct strpush *strpush; /* for pushing strings at this level */
1237         struct strpush basestrpush; /* so pushing one is fast */
1238
1239         /* Remember last two characters for pungetc. */
1240         int lastc[2];
1241
1242         /* Number of outstanding calls to pungetc. */
1243         int unget;
1244 };
1245
1246 static struct parsefile basepf;        /* top level input file */
1247 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1248 static int startlinno;                 /* line # where last token started */
1249 static char *commandname;              /* currently executing command */
1250 static struct strlist *cmdenviron;     /* environment for builtin command */
1251
1252
1253 /* ============ Message printing */
1254
1255 static void
1256 ash_vmsg(const char *msg, va_list ap)
1257 {
1258         fprintf(stderr, "%s: ", arg0);
1259         if (commandname) {
1260                 if (strcmp(arg0, commandname))
1261                         fprintf(stderr, "%s: ", commandname);
1262                 if (!iflag || g_parsefile->pf_fd > 0)
1263                         fprintf(stderr, "line %d: ", startlinno);
1264         }
1265         vfprintf(stderr, msg, ap);
1266         newline_and_flush(stderr);
1267 }
1268
1269 /*
1270  * Exverror is called to raise the error exception.  If the second argument
1271  * is not NULL then error prints an error message using printf style
1272  * formatting.  It then raises the error exception.
1273  */
1274 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1275 static void
1276 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1277 {
1278 #if DEBUG
1279         if (msg) {
1280                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1281                 TRACEV((msg, ap));
1282         } else
1283                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1284         if (msg)
1285 #endif
1286                 ash_vmsg(msg, ap);
1287
1288         flush_stdout_stderr();
1289         raise_exception(cond);
1290         /* NOTREACHED */
1291 }
1292
1293 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1294 static void
1295 ash_msg_and_raise_error(const char *msg, ...)
1296 {
1297         va_list ap;
1298
1299         exitstatus = 2;
1300
1301         va_start(ap, msg);
1302         ash_vmsg_and_raise(EXERROR, msg, ap);
1303         /* NOTREACHED */
1304         va_end(ap);
1305 }
1306
1307 static void raise_error_syntax(const char *) NORETURN;
1308 static void
1309 raise_error_syntax(const char *msg)
1310 {
1311         ash_msg_and_raise_error("syntax error: %s", msg);
1312         /* NOTREACHED */
1313 }
1314
1315 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1316 static void
1317 ash_msg_and_raise(int cond, const char *msg, ...)
1318 {
1319         va_list ap;
1320
1321         va_start(ap, msg);
1322         ash_vmsg_and_raise(cond, msg, ap);
1323         /* NOTREACHED */
1324         va_end(ap);
1325 }
1326
1327 /*
1328  * error/warning routines for external builtins
1329  */
1330 static void
1331 ash_msg(const char *fmt, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, fmt);
1336         ash_vmsg(fmt, ap);
1337         va_end(ap);
1338 }
1339
1340 /*
1341  * Return a string describing an error.  The returned string may be a
1342  * pointer to a static buffer that will be overwritten on the next call.
1343  * Action describes the operation that got the error.
1344  */
1345 static const char *
1346 errmsg(int e, const char *em)
1347 {
1348         if (e == ENOENT || e == ENOTDIR) {
1349                 return em;
1350         }
1351         return strerror(e);
1352 }
1353
1354
1355 /* ============ Memory allocation */
1356
1357 #if 0
1358 /* I consider these wrappers nearly useless:
1359  * ok, they return you to nearest exception handler, but
1360  * how much memory do you leak in the process, making
1361  * memory starvation worse?
1362  */
1363 static void *
1364 ckrealloc(void * p, size_t nbytes)
1365 {
1366         p = realloc(p, nbytes);
1367         if (!p)
1368                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1369         return p;
1370 }
1371
1372 static void *
1373 ckmalloc(size_t nbytes)
1374 {
1375         return ckrealloc(NULL, nbytes);
1376 }
1377
1378 static void *
1379 ckzalloc(size_t nbytes)
1380 {
1381         return memset(ckmalloc(nbytes), 0, nbytes);
1382 }
1383
1384 static char *
1385 ckstrdup(const char *s)
1386 {
1387         char *p = strdup(s);
1388         if (!p)
1389                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1390         return p;
1391 }
1392 #else
1393 /* Using bbox equivalents. They exit if out of memory */
1394 # define ckrealloc xrealloc
1395 # define ckmalloc  xmalloc
1396 # define ckzalloc  xzalloc
1397 # define ckstrdup  xstrdup
1398 #endif
1399
1400 /*
1401  * It appears that grabstackstr() will barf with such alignments
1402  * because stalloc() will return a string allocated in a new stackblock.
1403  */
1404 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1405 enum {
1406         /* Most machines require the value returned from malloc to be aligned
1407          * in some way.  The following macro will get this right
1408          * on many machines.  */
1409         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1410         /* Minimum size of a block */
1411         MINSIZE = SHELL_ALIGN(504),
1412 };
1413
1414 struct stack_block {
1415         struct stack_block *prev;
1416         char space[MINSIZE];
1417 };
1418
1419 struct stackmark {
1420         struct stack_block *stackp;
1421         char *stacknxt;
1422         size_t stacknleft;
1423 };
1424
1425
1426 struct globals_memstack {
1427         struct stack_block *g_stackp; // = &stackbase;
1428         char *g_stacknxt; // = stackbase.space;
1429         char *sstrend; // = stackbase.space + MINSIZE;
1430         size_t g_stacknleft; // = MINSIZE;
1431         struct stack_block stackbase;
1432 };
1433 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1434 #define G_memstack (*ash_ptr_to_globals_memstack)
1435 #define g_stackp     (G_memstack.g_stackp    )
1436 #define g_stacknxt   (G_memstack.g_stacknxt  )
1437 #define sstrend      (G_memstack.sstrend     )
1438 #define g_stacknleft (G_memstack.g_stacknleft)
1439 #define stackbase    (G_memstack.stackbase   )
1440 #define INIT_G_memstack() do { \
1441         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1442         barrier(); \
1443         g_stackp = &stackbase; \
1444         g_stacknxt = stackbase.space; \
1445         g_stacknleft = MINSIZE; \
1446         sstrend = stackbase.space + MINSIZE; \
1447 } while (0)
1448
1449
1450 #define stackblock()     ((void *)g_stacknxt)
1451 #define stackblocksize() g_stacknleft
1452
1453 /*
1454  * Parse trees for commands are allocated in lifo order, so we use a stack
1455  * to make this more efficient, and also to avoid all sorts of exception
1456  * handling code to handle interrupts in the middle of a parse.
1457  *
1458  * The size 504 was chosen because the Ultrix malloc handles that size
1459  * well.
1460  */
1461 static void *
1462 stalloc(size_t nbytes)
1463 {
1464         char *p;
1465         size_t aligned;
1466
1467         aligned = SHELL_ALIGN(nbytes);
1468         if (aligned > g_stacknleft) {
1469                 size_t len;
1470                 size_t blocksize;
1471                 struct stack_block *sp;
1472
1473                 blocksize = aligned;
1474                 if (blocksize < MINSIZE)
1475                         blocksize = MINSIZE;
1476                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1477                 if (len < blocksize)
1478                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1479                 INT_OFF;
1480                 sp = ckmalloc(len);
1481                 sp->prev = g_stackp;
1482                 g_stacknxt = sp->space;
1483                 g_stacknleft = blocksize;
1484                 sstrend = g_stacknxt + blocksize;
1485                 g_stackp = sp;
1486                 INT_ON;
1487         }
1488         p = g_stacknxt;
1489         g_stacknxt += aligned;
1490         g_stacknleft -= aligned;
1491         return p;
1492 }
1493
1494 static void *
1495 stzalloc(size_t nbytes)
1496 {
1497         return memset(stalloc(nbytes), 0, nbytes);
1498 }
1499
1500 static void
1501 stunalloc(void *p)
1502 {
1503 #if DEBUG
1504         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1505                 write(STDERR_FILENO, "stunalloc\n", 10);
1506                 abort();
1507         }
1508 #endif
1509         g_stacknleft += g_stacknxt - (char *)p;
1510         g_stacknxt = p;
1511 }
1512
1513 /*
1514  * Like strdup but works with the ash stack.
1515  */
1516 static char *
1517 sstrdup(const char *p)
1518 {
1519         size_t len = strlen(p) + 1;
1520         return memcpy(stalloc(len), p, len);
1521 }
1522
1523 static inline void
1524 grabstackblock(size_t len)
1525 {
1526         stalloc(len);
1527 }
1528
1529 static void
1530 pushstackmark(struct stackmark *mark, size_t len)
1531 {
1532         mark->stackp = g_stackp;
1533         mark->stacknxt = g_stacknxt;
1534         mark->stacknleft = g_stacknleft;
1535         grabstackblock(len);
1536 }
1537
1538 static void
1539 setstackmark(struct stackmark *mark)
1540 {
1541         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1542 }
1543
1544 static void
1545 popstackmark(struct stackmark *mark)
1546 {
1547         struct stack_block *sp;
1548
1549         if (!mark->stackp)
1550                 return;
1551
1552         INT_OFF;
1553         while (g_stackp != mark->stackp) {
1554                 sp = g_stackp;
1555                 g_stackp = sp->prev;
1556                 free(sp);
1557         }
1558         g_stacknxt = mark->stacknxt;
1559         g_stacknleft = mark->stacknleft;
1560         sstrend = mark->stacknxt + mark->stacknleft;
1561         INT_ON;
1562 }
1563
1564 /*
1565  * When the parser reads in a string, it wants to stick the string on the
1566  * stack and only adjust the stack pointer when it knows how big the
1567  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1568  * of space on top of the stack and stackblocklen returns the length of
1569  * this block.  Growstackblock will grow this space by at least one byte,
1570  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1571  * part of the block that has been used.
1572  */
1573 static void
1574 growstackblock(void)
1575 {
1576         size_t newlen;
1577
1578         newlen = g_stacknleft * 2;
1579         if (newlen < g_stacknleft)
1580                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1581         if (newlen < 128)
1582                 newlen += 128;
1583
1584         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1585                 struct stack_block *sp;
1586                 struct stack_block *prevstackp;
1587                 size_t grosslen;
1588
1589                 INT_OFF;
1590                 sp = g_stackp;
1591                 prevstackp = sp->prev;
1592                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1593                 sp = ckrealloc(sp, grosslen);
1594                 sp->prev = prevstackp;
1595                 g_stackp = sp;
1596                 g_stacknxt = sp->space;
1597                 g_stacknleft = newlen;
1598                 sstrend = sp->space + newlen;
1599                 INT_ON;
1600         } else {
1601                 char *oldspace = g_stacknxt;
1602                 size_t oldlen = g_stacknleft;
1603                 char *p = stalloc(newlen);
1604
1605                 /* free the space we just allocated */
1606                 g_stacknxt = memcpy(p, oldspace, oldlen);
1607                 g_stacknleft += newlen;
1608         }
1609 }
1610
1611 /*
1612  * The following routines are somewhat easier to use than the above.
1613  * The user declares a variable of type STACKSTR, which may be declared
1614  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1615  * the user uses the macro STPUTC to add characters to the string.  In
1616  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1617  * grown as necessary.  When the user is done, she can just leave the
1618  * string there and refer to it using stackblock().  Or she can allocate
1619  * the space for it using grabstackstr().  If it is necessary to allow
1620  * someone else to use the stack temporarily and then continue to grow
1621  * the string, the user should use grabstack to allocate the space, and
1622  * then call ungrabstr(p) to return to the previous mode of operation.
1623  *
1624  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1625  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1626  * is space for at least one character.
1627  */
1628 static void *
1629 growstackstr(void)
1630 {
1631         size_t len = stackblocksize();
1632         growstackblock();
1633         return (char *)stackblock() + len;
1634 }
1635
1636 /*
1637  * Called from CHECKSTRSPACE.
1638  */
1639 static char *
1640 makestrspace(size_t newlen, char *p)
1641 {
1642         size_t len = p - g_stacknxt;
1643         size_t size;
1644
1645         for (;;) {
1646                 size_t nleft;
1647
1648                 size = stackblocksize();
1649                 nleft = size - len;
1650                 if (nleft >= newlen)
1651                         break;
1652                 growstackblock();
1653         }
1654         return (char *)stackblock() + len;
1655 }
1656
1657 static char *
1658 stack_nputstr(const char *s, size_t n, char *p)
1659 {
1660         p = makestrspace(n, p);
1661         p = (char *)mempcpy(p, s, n);
1662         return p;
1663 }
1664
1665 static char *
1666 stack_putstr(const char *s, char *p)
1667 {
1668         return stack_nputstr(s, strlen(s), p);
1669 }
1670
1671 static char *
1672 _STPUTC(int c, char *p)
1673 {
1674         if (p == sstrend)
1675                 p = growstackstr();
1676         *p++ = c;
1677         return p;
1678 }
1679
1680 #define STARTSTACKSTR(p)        ((p) = stackblock())
1681 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1682 #define CHECKSTRSPACE(n, p) do { \
1683         char *q = (p); \
1684         size_t l = (n); \
1685         size_t m = sstrend - q; \
1686         if (l > m) \
1687                 (p) = makestrspace(l, q); \
1688 } while (0)
1689 #define USTPUTC(c, p)           (*(p)++ = (c))
1690 #define STACKSTRNUL(p) do { \
1691         if ((p) == sstrend) \
1692                 (p) = growstackstr(); \
1693         *(p) = '\0'; \
1694 } while (0)
1695 #define STUNPUTC(p)             (--(p))
1696 #define STTOPC(p)               ((p)[-1])
1697 #define STADJUST(amount, p)     ((p) += (amount))
1698
1699 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1700 #define ungrabstackstr(s, p)    stunalloc(s)
1701 #define stackstrend()           ((void *)sstrend)
1702
1703
1704 /* ============ String helpers */
1705
1706 /*
1707  * prefix -- see if pfx is a prefix of string.
1708  */
1709 static char *
1710 prefix(const char *string, const char *pfx)
1711 {
1712         while (*pfx) {
1713                 if (*pfx++ != *string++)
1714                         return NULL;
1715         }
1716         return (char *) string;
1717 }
1718
1719 /*
1720  * Check for a valid number.  This should be elsewhere.
1721  */
1722 static int
1723 is_number(const char *p)
1724 {
1725         do {
1726                 if (!isdigit(*p))
1727                         return 0;
1728         } while (*++p != '\0');
1729         return 1;
1730 }
1731
1732 /*
1733  * Convert a string of digits to an integer, printing an error message on
1734  * failure.
1735  */
1736 static int
1737 number(const char *s)
1738 {
1739         if (!is_number(s))
1740                 ash_msg_and_raise_error(msg_illnum, s);
1741         return atoi(s);
1742 }
1743
1744 /*
1745  * Produce a single quoted string suitable as input to the shell.
1746  * The return string is allocated on the stack.
1747  */
1748 static char *
1749 single_quote(const char *s)
1750 {
1751         char *p;
1752
1753         STARTSTACKSTR(p);
1754
1755         do {
1756                 char *q;
1757                 size_t len;
1758
1759                 len = strchrnul(s, '\'') - s;
1760
1761                 q = p = makestrspace(len + 3, p);
1762
1763                 *q++ = '\'';
1764                 q = (char *)mempcpy(q, s, len);
1765                 *q++ = '\'';
1766                 s += len;
1767
1768                 STADJUST(q - p, p);
1769
1770                 if (*s != '\'')
1771                         break;
1772                 len = 0;
1773                 do len++; while (*++s == '\'');
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '"';
1778                 q = (char *)mempcpy(q, s - len, len);
1779                 *q++ = '"';
1780
1781                 STADJUST(q - p, p);
1782         } while (*s);
1783
1784         USTPUTC('\0', p);
1785
1786         return stackblock();
1787 }
1788
1789 /*
1790  * Produce a possibly single quoted string suitable as input to the shell.
1791  * If quoting was done, the return string is allocated on the stack,
1792  * otherwise a pointer to the original string is returned.
1793  */
1794 static const char *
1795 maybe_single_quote(const char *s)
1796 {
1797         const char *p = s;
1798
1799         while (*p) {
1800                 /* Assuming ACSII */
1801                 /* quote ctrl_chars space !"#$%&'()* */
1802                 if (*p < '+')
1803                         goto need_quoting;
1804                 /* quote ;<=>? */
1805                 if (*p >= ';' && *p <= '?')
1806                         goto need_quoting;
1807                 /* quote `[\ */
1808                 if (*p == '`')
1809                         goto need_quoting;
1810                 if (*p == '[')
1811                         goto need_quoting;
1812                 if (*p == '\\')
1813                         goto need_quoting;
1814                 /* quote {|}~ DEL and high bytes */
1815                 if (*p > 'z')
1816                         goto need_quoting;
1817                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1818                 /* TODO: maybe avoid quoting % */
1819                 p++;
1820         }
1821         return s;
1822
1823  need_quoting:
1824         return single_quote(s);
1825 }
1826
1827
1828 /* ============ nextopt */
1829
1830 static char **argptr;                  /* argument list for builtin commands */
1831 static char *optionarg;                /* set by nextopt (like getopt) */
1832 static char *optptr;                   /* used by nextopt */
1833
1834 /*
1835  * XXX - should get rid of. Have all builtins use getopt(3).
1836  * The library getopt must have the BSD extension static variable
1837  * "optreset", otherwise it can't be used within the shell safely.
1838  *
1839  * Standard option processing (a la getopt) for builtin routines.
1840  * The only argument that is passed to nextopt is the option string;
1841  * the other arguments are unnecessary. It returns the character,
1842  * or '\0' on end of input.
1843  */
1844 static int
1845 nextopt(const char *optstring)
1846 {
1847         char *p;
1848         const char *q;
1849         char c;
1850
1851         p = optptr;
1852         if (p == NULL || *p == '\0') {
1853                 /* We ate entire "-param", take next one */
1854                 p = *argptr;
1855                 if (p == NULL)
1856                         return '\0';
1857                 if (*p != '-')
1858                         return '\0';
1859                 if (*++p == '\0') /* just "-" ? */
1860                         return '\0';
1861                 argptr++;
1862                 if (LONE_DASH(p)) /* "--" ? */
1863                         return '\0';
1864                 /* p => next "-param" */
1865         }
1866         /* p => some option char in the middle of a "-param" */
1867         c = *p++;
1868         for (q = optstring; *q != c;) {
1869                 if (*q == '\0')
1870                         ash_msg_and_raise_error("illegal option -%c", c);
1871                 if (*++q == ':')
1872                         q++;
1873         }
1874         if (*++q == ':') {
1875                 if (*p == '\0') {
1876                         p = *argptr++;
1877                         if (p == NULL)
1878                                 ash_msg_and_raise_error("no arg for -%c option", c);
1879                 }
1880                 optionarg = p;
1881                 p = NULL;
1882         }
1883         optptr = p;
1884         return c;
1885 }
1886
1887
1888 /* ============ Shell variables */
1889
1890 /*
1891  * The parsefile structure pointed to by the global variable parsefile
1892  * contains information about the current file being read.
1893  */
1894 struct shparam {
1895         int nparam;             /* # of positional parameters (without $0) */
1896 #if ENABLE_ASH_GETOPTS
1897         int optind;             /* next parameter to be processed by getopts */
1898         int optoff;             /* used by getopts */
1899 #endif
1900         unsigned char malloced; /* if parameter list dynamically allocated */
1901         char **p;               /* parameter list */
1902 };
1903
1904 /*
1905  * Free the list of positional parameters.
1906  */
1907 static void
1908 freeparam(volatile struct shparam *param)
1909 {
1910         if (param->malloced) {
1911                 char **ap, **ap1;
1912                 ap = ap1 = param->p;
1913                 while (*ap)
1914                         free(*ap++);
1915                 free(ap1);
1916         }
1917 }
1918
1919 #if ENABLE_ASH_GETOPTS
1920 static void FAST_FUNC getoptsreset(const char *value);
1921 #endif
1922
1923 struct var {
1924         struct var *next;               /* next entry in hash list */
1925         int flags;                      /* flags are defined above */
1926         const char *var_text;           /* name=value */
1927         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1928                                         /* the variable gets set/unset */
1929 };
1930
1931 struct localvar {
1932         struct localvar *next;          /* next local variable in list */
1933         struct var *vp;                 /* the variable that was made local */
1934         int flags;                      /* saved flags */
1935         const char *text;               /* saved text */
1936 };
1937
1938 /* flags */
1939 #define VEXPORT         0x01    /* variable is exported */
1940 #define VREADONLY       0x02    /* variable cannot be modified */
1941 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1942 #define VTEXTFIXED      0x08    /* text is statically allocated */
1943 #define VSTACK          0x10    /* text is allocated on the stack */
1944 #define VUNSET          0x20    /* the variable is not set */
1945 #define VNOFUNC         0x40    /* don't call the callback function */
1946 #define VNOSET          0x80    /* do not set variable - just readonly test */
1947 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1948 #if ENABLE_ASH_RANDOM_SUPPORT
1949 # define VDYNAMIC       0x200   /* dynamic variable */
1950 #else
1951 # define VDYNAMIC       0
1952 #endif
1953
1954
1955 /* Need to be before varinit_data[] */
1956 #if ENABLE_LOCALE_SUPPORT
1957 static void FAST_FUNC
1958 change_lc_all(const char *value)
1959 {
1960         if (value && *value != '\0')
1961                 setlocale(LC_ALL, value);
1962 }
1963 static void FAST_FUNC
1964 change_lc_ctype(const char *value)
1965 {
1966         if (value && *value != '\0')
1967                 setlocale(LC_CTYPE, value);
1968 }
1969 #endif
1970 #if ENABLE_ASH_MAIL
1971 static void chkmail(void);
1972 static void changemail(const char *var_value) FAST_FUNC;
1973 #else
1974 # define chkmail()  ((void)0)
1975 #endif
1976 static void changepath(const char *) FAST_FUNC;
1977 #if ENABLE_ASH_RANDOM_SUPPORT
1978 static void change_random(const char *) FAST_FUNC;
1979 #endif
1980
1981 static const struct {
1982         int flags;
1983         const char *var_text;
1984         void (*var_func)(const char *) FAST_FUNC;
1985 } varinit_data[] = {
1986         /*
1987          * Note: VEXPORT would not work correctly here for NOFORK applets:
1988          * some environment strings may be constant.
1989          */
1990         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1991 #if ENABLE_ASH_MAIL
1992         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1993         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1994 #endif
1995         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1996         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1997         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1998         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1999 #if ENABLE_ASH_GETOPTS
2000         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2001 #endif
2002 #if ENABLE_ASH_RANDOM_SUPPORT
2003         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2004 #endif
2005 #if ENABLE_LOCALE_SUPPORT
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2008 #endif
2009 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2010         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2011 #endif
2012 };
2013
2014 struct redirtab;
2015
2016 struct globals_var {
2017         struct shparam shellparam;      /* $@ current positional parameters */
2018         struct redirtab *redirlist;
2019         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2020         struct var *vartab[VTABSIZE];
2021         struct var varinit[ARRAY_SIZE(varinit_data)];
2022 };
2023 extern struct globals_var *const ash_ptr_to_globals_var;
2024 #define G_var (*ash_ptr_to_globals_var)
2025 #define shellparam    (G_var.shellparam   )
2026 //#define redirlist     (G_var.redirlist    )
2027 #define preverrout_fd (G_var.preverrout_fd)
2028 #define vartab        (G_var.vartab       )
2029 #define varinit       (G_var.varinit      )
2030 #define INIT_G_var() do { \
2031         unsigned i; \
2032         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2033         barrier(); \
2034         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2035                 varinit[i].flags    = varinit_data[i].flags; \
2036                 varinit[i].var_text = varinit_data[i].var_text; \
2037                 varinit[i].var_func = varinit_data[i].var_func; \
2038         } \
2039 } while (0)
2040
2041 #define vifs      varinit[0]
2042 #if ENABLE_ASH_MAIL
2043 # define vmail    (&vifs)[1]
2044 # define vmpath   (&vmail)[1]
2045 # define vpath    (&vmpath)[1]
2046 #else
2047 # define vpath    (&vifs)[1]
2048 #endif
2049 #define vps1      (&vpath)[1]
2050 #define vps2      (&vps1)[1]
2051 #define vps4      (&vps2)[1]
2052 #if ENABLE_ASH_GETOPTS
2053 # define voptind  (&vps4)[1]
2054 # if ENABLE_ASH_RANDOM_SUPPORT
2055 #  define vrandom (&voptind)[1]
2056 # endif
2057 #else
2058 # if ENABLE_ASH_RANDOM_SUPPORT
2059 #  define vrandom (&vps4)[1]
2060 # endif
2061 #endif
2062
2063 /*
2064  * The following macros access the values of the above variables.
2065  * They have to skip over the name.  They return the null string
2066  * for unset variables.
2067  */
2068 #define ifsval()        (vifs.var_text + 4)
2069 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2070 #if ENABLE_ASH_MAIL
2071 # define mailval()      (vmail.var_text + 5)
2072 # define mpathval()     (vmpath.var_text + 9)
2073 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2074 #endif
2075 #define pathval()       (vpath.var_text + 5)
2076 #define ps1val()        (vps1.var_text + 4)
2077 #define ps2val()        (vps2.var_text + 4)
2078 #define ps4val()        (vps4.var_text + 4)
2079 #if ENABLE_ASH_GETOPTS
2080 # define optindval()    (voptind.var_text + 7)
2081 #endif
2082
2083 #if ENABLE_ASH_GETOPTS
2084 static void FAST_FUNC
2085 getoptsreset(const char *value)
2086 {
2087         shellparam.optind = number(value) ?: 1;
2088         shellparam.optoff = -1;
2089 }
2090 #endif
2091
2092 /*
2093  * Compares two strings up to the first = or '\0'.  The first
2094  * string must be terminated by '='; the second may be terminated by
2095  * either '=' or '\0'.
2096  */
2097 static int
2098 varcmp(const char *p, const char *q)
2099 {
2100         int c, d;
2101
2102         while ((c = *p) == (d = *q)) {
2103                 if (c == '\0' || c == '=')
2104                         goto out;
2105                 p++;
2106                 q++;
2107         }
2108         if (c == '=')
2109                 c = '\0';
2110         if (d == '=')
2111                 d = '\0';
2112  out:
2113         return c - d;
2114 }
2115
2116 /*
2117  * Find the appropriate entry in the hash table from the name.
2118  */
2119 static struct var **
2120 hashvar(const char *p)
2121 {
2122         unsigned hashval;
2123
2124         hashval = ((unsigned char) *p) << 4;
2125         while (*p && *p != '=')
2126                 hashval += (unsigned char) *p++;
2127         return &vartab[hashval % VTABSIZE];
2128 }
2129
2130 static int
2131 vpcmp(const void *a, const void *b)
2132 {
2133         return varcmp(*(const char **)a, *(const char **)b);
2134 }
2135
2136 /*
2137  * This routine initializes the builtin variables.
2138  */
2139 static void
2140 initvar(void)
2141 {
2142         struct var *vp;
2143         struct var *end;
2144         struct var **vpp;
2145
2146         /*
2147          * PS1 depends on uid
2148          */
2149 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2150         vps1.var_text = "PS1=\\w \\$ ";
2151 #else
2152         if (!geteuid())
2153                 vps1.var_text = "PS1=# ";
2154 #endif
2155         vp = varinit;
2156         end = vp + ARRAY_SIZE(varinit);
2157         do {
2158                 vpp = hashvar(vp->var_text);
2159                 vp->next = *vpp;
2160                 *vpp = vp;
2161         } while (++vp < end);
2162 }
2163
2164 static struct var **
2165 findvar(struct var **vpp, const char *name)
2166 {
2167         for (; *vpp; vpp = &(*vpp)->next) {
2168                 if (varcmp((*vpp)->var_text, name) == 0) {
2169                         break;
2170                 }
2171         }
2172         return vpp;
2173 }
2174
2175 /*
2176  * Find the value of a variable.  Returns NULL if not set.
2177  */
2178 static const char* FAST_FUNC
2179 lookupvar(const char *name)
2180 {
2181         struct var *v;
2182
2183         v = *findvar(hashvar(name), name);
2184         if (v) {
2185 #if ENABLE_ASH_RANDOM_SUPPORT
2186         /*
2187          * Dynamic variables are implemented roughly the same way they are
2188          * in bash. Namely, they're "special" so long as they aren't unset.
2189          * As soon as they're unset, they're no longer dynamic, and dynamic
2190          * lookup will no longer happen at that point. -- PFM.
2191          */
2192                 if (v->flags & VDYNAMIC)
2193                         v->var_func(NULL);
2194 #endif
2195                 if (!(v->flags & VUNSET))
2196                         return var_end(v->var_text);
2197         }
2198         return NULL;
2199 }
2200
2201 #if ENABLE_UNICODE_SUPPORT
2202 static void
2203 reinit_unicode_for_ash(void)
2204 {
2205         /* Unicode support should be activated even if LANG is set
2206          * _during_ shell execution, not only if it was set when
2207          * shell was started. Therefore, re-check LANG every time:
2208          */
2209         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2210          || ENABLE_UNICODE_USING_LOCALE
2211         ) {
2212                 const char *s = lookupvar("LC_ALL");
2213                 if (!s) s = lookupvar("LC_CTYPE");
2214                 if (!s) s = lookupvar("LANG");
2215                 reinit_unicode(s);
2216         }
2217 }
2218 #else
2219 # define reinit_unicode_for_ash() ((void)0)
2220 #endif
2221
2222 /*
2223  * Search the environment of a builtin command.
2224  */
2225 static const char *
2226 bltinlookup(const char *name)
2227 {
2228         struct strlist *sp;
2229
2230         for (sp = cmdenviron; sp; sp = sp->next) {
2231                 if (varcmp(sp->text, name) == 0)
2232                         return var_end(sp->text);
2233         }
2234         return lookupvar(name);
2235 }
2236
2237 /*
2238  * Same as setvar except that the variable and value are passed in
2239  * the first argument as name=value.  Since the first argument will
2240  * be actually stored in the table, it should not be a string that
2241  * will go away.
2242  * Called with interrupts off.
2243  */
2244 static void
2245 setvareq(char *s, int flags)
2246 {
2247         struct var *vp, **vpp;
2248
2249         vpp = hashvar(s);
2250         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2251         vp = *findvar(vpp, s);
2252         if (vp) {
2253                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2254                         const char *n;
2255
2256                         if (flags & VNOSAVE)
2257                                 free(s);
2258                         n = vp->var_text;
2259                         exitstatus = 1;
2260                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2261                 }
2262
2263                 if (flags & VNOSET)
2264                         return;
2265
2266                 if (vp->var_func && !(flags & VNOFUNC))
2267                         vp->var_func(var_end(s));
2268
2269                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2270                         free((char*)vp->var_text);
2271
2272                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2273         } else {
2274                 /* variable s is not found */
2275                 if (flags & VNOSET)
2276                         return;
2277                 vp = ckzalloc(sizeof(*vp));
2278                 vp->next = *vpp;
2279                 /*vp->func = NULL; - ckzalloc did it */
2280                 *vpp = vp;
2281         }
2282         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2283                 s = ckstrdup(s);
2284         vp->var_text = s;
2285         vp->flags = flags;
2286 }
2287
2288 /*
2289  * Set the value of a variable.  The flags argument is ored with the
2290  * flags of the variable.  If val is NULL, the variable is unset.
2291  */
2292 static void
2293 setvar(const char *name, const char *val, int flags)
2294 {
2295         const char *q;
2296         char *p;
2297         char *nameeq;
2298         size_t namelen;
2299         size_t vallen;
2300
2301         q = endofname(name);
2302         p = strchrnul(q, '=');
2303         namelen = p - name;
2304         if (!namelen || p != q)
2305                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2306         vallen = 0;
2307         if (val == NULL) {
2308                 flags |= VUNSET;
2309         } else {
2310                 vallen = strlen(val);
2311         }
2312
2313         INT_OFF;
2314         nameeq = ckmalloc(namelen + vallen + 2);
2315         p = mempcpy(nameeq, name, namelen);
2316         if (val) {
2317                 *p++ = '=';
2318                 p = mempcpy(p, val, vallen);
2319         }
2320         *p = '\0';
2321         setvareq(nameeq, flags | VNOSAVE);
2322         INT_ON;
2323 }
2324
2325 static void FAST_FUNC
2326 setvar0(const char *name, const char *val)
2327 {
2328         setvar(name, val, 0);
2329 }
2330
2331 /*
2332  * Unset the specified variable.
2333  */
2334 static int
2335 unsetvar(const char *s)
2336 {
2337         struct var **vpp;
2338         struct var *vp;
2339         int retval;
2340
2341         vpp = findvar(hashvar(s), s);
2342         vp = *vpp;
2343         retval = 2;
2344         if (vp) {
2345                 int flags = vp->flags;
2346
2347                 retval = 1;
2348                 if (flags & VREADONLY)
2349                         goto out;
2350 #if ENABLE_ASH_RANDOM_SUPPORT
2351                 vp->flags &= ~VDYNAMIC;
2352 #endif
2353                 if (flags & VUNSET)
2354                         goto ok;
2355                 if ((flags & VSTRFIXED) == 0) {
2356                         INT_OFF;
2357                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2358                                 free((char*)vp->var_text);
2359                         *vpp = vp->next;
2360                         free(vp);
2361                         INT_ON;
2362                 } else {
2363                         setvar0(s, NULL);
2364                         vp->flags &= ~VEXPORT;
2365                 }
2366  ok:
2367                 retval = 0;
2368         }
2369  out:
2370         return retval;
2371 }
2372
2373 /*
2374  * Process a linked list of variable assignments.
2375  */
2376 static void
2377 listsetvar(struct strlist *list_set_var, int flags)
2378 {
2379         struct strlist *lp = list_set_var;
2380
2381         if (!lp)
2382                 return;
2383         INT_OFF;
2384         do {
2385                 setvareq(lp->text, flags);
2386                 lp = lp->next;
2387         } while (lp);
2388         INT_ON;
2389 }
2390
2391 /*
2392  * Generate a list of variables satisfying the given conditions.
2393  */
2394 static char **
2395 listvars(int on, int off, char ***end)
2396 {
2397         struct var **vpp;
2398         struct var *vp;
2399         char **ep;
2400         int mask;
2401
2402         STARTSTACKSTR(ep);
2403         vpp = vartab;
2404         mask = on | off;
2405         do {
2406                 for (vp = *vpp; vp; vp = vp->next) {
2407                         if ((vp->flags & mask) == on) {
2408                                 if (ep == stackstrend())
2409                                         ep = growstackstr();
2410                                 *ep++ = (char*)vp->var_text;
2411                         }
2412                 }
2413         } while (++vpp < vartab + VTABSIZE);
2414         if (ep == stackstrend())
2415                 ep = growstackstr();
2416         if (end)
2417                 *end = ep;
2418         *ep++ = NULL;
2419         return grabstackstr(ep);
2420 }
2421
2422
2423 /* ============ Path search helper
2424  *
2425  * The variable path (passed by reference) should be set to the start
2426  * of the path before the first call; path_advance will update
2427  * this value as it proceeds.  Successive calls to path_advance will return
2428  * the possible path expansions in sequence.  If an option (indicated by
2429  * a percent sign) appears in the path entry then the global variable
2430  * pathopt will be set to point to it; otherwise pathopt will be set to
2431  * NULL.
2432  */
2433 static const char *pathopt;     /* set by path_advance */
2434
2435 static char *
2436 path_advance(const char **path, const char *name)
2437 {
2438         const char *p;
2439         char *q;
2440         const char *start;
2441         size_t len;
2442
2443         if (*path == NULL)
2444                 return NULL;
2445         start = *path;
2446         for (p = start; *p && *p != ':' && *p != '%'; p++)
2447                 continue;
2448         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2449         while (stackblocksize() < len)
2450                 growstackblock();
2451         q = stackblock();
2452         if (p != start) {
2453                 q = mempcpy(q, start, p - start);
2454                 *q++ = '/';
2455         }
2456         strcpy(q, name);
2457         pathopt = NULL;
2458         if (*p == '%') {
2459                 pathopt = ++p;
2460                 while (*p && *p != ':')
2461                         p++;
2462         }
2463         if (*p == ':')
2464                 *path = p + 1;
2465         else
2466                 *path = NULL;
2467         return stalloc(len);
2468 }
2469
2470
2471 /* ============ Prompt */
2472
2473 static smallint doprompt;                   /* if set, prompt the user */
2474 static smallint needprompt;                 /* true if interactive and at start of line */
2475
2476 #if ENABLE_FEATURE_EDITING
2477 static line_input_t *line_input_state;
2478 static const char *cmdedit_prompt;
2479 static void
2480 putprompt(const char *s)
2481 {
2482         if (ENABLE_ASH_EXPAND_PRMT) {
2483                 free((char*)cmdedit_prompt);
2484                 cmdedit_prompt = ckstrdup(s);
2485                 return;
2486         }
2487         cmdedit_prompt = s;
2488 }
2489 #else
2490 static void
2491 putprompt(const char *s)
2492 {
2493         out2str(s);
2494 }
2495 #endif
2496
2497 /* expandstr() needs parsing machinery, so it is far away ahead... */
2498 static const char *expandstr(const char *ps);
2499
2500 static void
2501 setprompt_if(smallint do_set, int whichprompt)
2502 {
2503         const char *prompt;
2504         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2505
2506         if (!do_set)
2507                 return;
2508
2509         needprompt = 0;
2510
2511         switch (whichprompt) {
2512         case 1:
2513                 prompt = ps1val();
2514                 break;
2515         case 2:
2516                 prompt = ps2val();
2517                 break;
2518         default:                        /* 0 */
2519                 prompt = nullstr;
2520         }
2521 #if ENABLE_ASH_EXPAND_PRMT
2522         pushstackmark(&smark, stackblocksize());
2523         putprompt(expandstr(prompt));
2524         popstackmark(&smark);
2525 #else
2526         putprompt(prompt);
2527 #endif
2528 }
2529
2530
2531 /* ============ The cd and pwd commands */
2532
2533 #define CD_PHYSICAL 1
2534 #define CD_PRINT 2
2535
2536 static int
2537 cdopt(void)
2538 {
2539         int flags = 0;
2540         int i, j;
2541
2542         j = 'L';
2543         while ((i = nextopt("LP")) != '\0') {
2544                 if (i != j) {
2545                         flags ^= CD_PHYSICAL;
2546                         j = i;
2547                 }
2548         }
2549
2550         return flags;
2551 }
2552
2553 /*
2554  * Update curdir (the name of the current directory) in response to a
2555  * cd command.
2556  */
2557 static const char *
2558 updatepwd(const char *dir)
2559 {
2560         char *new;
2561         char *p;
2562         char *cdcomppath;
2563         const char *lim;
2564
2565         cdcomppath = sstrdup(dir);
2566         STARTSTACKSTR(new);
2567         if (*dir != '/') {
2568                 if (curdir == nullstr)
2569                         return 0;
2570                 new = stack_putstr(curdir, new);
2571         }
2572         new = makestrspace(strlen(dir) + 2, new);
2573         lim = (char *)stackblock() + 1;
2574         if (*dir != '/') {
2575                 if (new[-1] != '/')
2576                         USTPUTC('/', new);
2577                 if (new > lim && *lim == '/')
2578                         lim++;
2579         } else {
2580                 USTPUTC('/', new);
2581                 cdcomppath++;
2582                 if (dir[1] == '/' && dir[2] != '/') {
2583                         USTPUTC('/', new);
2584                         cdcomppath++;
2585                         lim++;
2586                 }
2587         }
2588         p = strtok(cdcomppath, "/");
2589         while (p) {
2590                 switch (*p) {
2591                 case '.':
2592                         if (p[1] == '.' && p[2] == '\0') {
2593                                 while (new > lim) {
2594                                         STUNPUTC(new);
2595                                         if (new[-1] == '/')
2596                                                 break;
2597                                 }
2598                                 break;
2599                         }
2600                         if (p[1] == '\0')
2601                                 break;
2602                         /* fall through */
2603                 default:
2604                         new = stack_putstr(p, new);
2605                         USTPUTC('/', new);
2606                 }
2607                 p = strtok(NULL, "/");
2608         }
2609         if (new > lim)
2610                 STUNPUTC(new);
2611         *new = 0;
2612         return stackblock();
2613 }
2614
2615 /*
2616  * Find out what the current directory is. If we already know the current
2617  * directory, this routine returns immediately.
2618  */
2619 static char *
2620 getpwd(void)
2621 {
2622         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2623         return dir ? dir : nullstr;
2624 }
2625
2626 static void
2627 setpwd(const char *val, int setold)
2628 {
2629         char *oldcur, *dir;
2630
2631         oldcur = dir = curdir;
2632
2633         if (setold) {
2634                 setvar("OLDPWD", oldcur, VEXPORT);
2635         }
2636         INT_OFF;
2637         if (physdir != nullstr) {
2638                 if (physdir != oldcur)
2639                         free(physdir);
2640                 physdir = nullstr;
2641         }
2642         if (oldcur == val || !val) {
2643                 char *s = getpwd();
2644                 physdir = s;
2645                 if (!val)
2646                         dir = s;
2647         } else
2648                 dir = ckstrdup(val);
2649         if (oldcur != dir && oldcur != nullstr) {
2650                 free(oldcur);
2651         }
2652         curdir = dir;
2653         INT_ON;
2654         setvar("PWD", dir, VEXPORT);
2655 }
2656
2657 static void hashcd(void);
2658
2659 /*
2660  * Actually do the chdir.  We also call hashcd to let other routines
2661  * know that the current directory has changed.
2662  */
2663 static int
2664 docd(const char *dest, int flags)
2665 {
2666         const char *dir = NULL;
2667         int err;
2668
2669         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2670
2671         INT_OFF;
2672         if (!(flags & CD_PHYSICAL)) {
2673                 dir = updatepwd(dest);
2674                 if (dir)
2675                         dest = dir;
2676         }
2677         err = chdir(dest);
2678         if (err)
2679                 goto out;
2680         setpwd(dir, 1);
2681         hashcd();
2682  out:
2683         INT_ON;
2684         return err;
2685 }
2686
2687 static int FAST_FUNC
2688 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2689 {
2690         const char *dest;
2691         const char *path;
2692         const char *p;
2693         char c;
2694         struct stat statb;
2695         int flags;
2696
2697         flags = cdopt();
2698         dest = *argptr;
2699         if (!dest)
2700                 dest = bltinlookup("HOME");
2701         else if (LONE_DASH(dest)) {
2702                 dest = bltinlookup("OLDPWD");
2703                 flags |= CD_PRINT;
2704         }
2705         if (!dest)
2706                 dest = nullstr;
2707         if (*dest == '/')
2708                 goto step6;
2709         if (*dest == '.') {
2710                 c = dest[1];
2711  dotdot:
2712                 switch (c) {
2713                 case '\0':
2714                 case '/':
2715                         goto step6;
2716                 case '.':
2717                         c = dest[2];
2718                         if (c != '.')
2719                                 goto dotdot;
2720                 }
2721         }
2722         if (!*dest)
2723                 dest = ".";
2724         path = bltinlookup("CDPATH");
2725         while (path) {
2726                 c = *path;
2727                 p = path_advance(&path, dest);
2728                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2729                         if (c && c != ':')
2730                                 flags |= CD_PRINT;
2731  docd:
2732                         if (!docd(p, flags))
2733                                 goto out;
2734                         goto err;
2735                 }
2736         }
2737
2738  step6:
2739         p = dest;
2740         goto docd;
2741
2742  err:
2743         ash_msg_and_raise_error("can't cd to %s", dest);
2744         /* NOTREACHED */
2745  out:
2746         if (flags & CD_PRINT)
2747                 out1fmt("%s\n", curdir);
2748         return 0;
2749 }
2750
2751 static int FAST_FUNC
2752 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2753 {
2754         int flags;
2755         const char *dir = curdir;
2756
2757         flags = cdopt();
2758         if (flags) {
2759                 if (physdir == nullstr)
2760                         setpwd(dir, 0);
2761                 dir = physdir;
2762         }
2763         out1fmt("%s\n", dir);
2764         return 0;
2765 }
2766
2767
2768 /* ============ ... */
2769
2770
2771 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2772
2773 /* Syntax classes */
2774 #define CWORD     0             /* character is nothing special */
2775 #define CNL       1             /* newline character */
2776 #define CBACK     2             /* a backslash character */
2777 #define CSQUOTE   3             /* single quote */
2778 #define CDQUOTE   4             /* double quote */
2779 #define CENDQUOTE 5             /* a terminating quote */
2780 #define CBQUOTE   6             /* backwards single quote */
2781 #define CVAR      7             /* a dollar sign */
2782 #define CENDVAR   8             /* a '}' character */
2783 #define CLP       9             /* a left paren in arithmetic */
2784 #define CRP      10             /* a right paren in arithmetic */
2785 #define CENDFILE 11             /* end of file */
2786 #define CCTL     12             /* like CWORD, except it must be escaped */
2787 #define CSPCL    13             /* these terminate a word */
2788 #define CIGN     14             /* character should be ignored */
2789
2790 #define PEOF     256
2791 #if ENABLE_ASH_ALIAS
2792 # define PEOA    257
2793 #endif
2794
2795 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2796
2797 #if ENABLE_FEATURE_SH_MATH
2798 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2799 #else
2800 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2801 #endif
2802 static const uint16_t S_I_T[] ALIGN2 = {
2803 #if ENABLE_ASH_ALIAS
2804         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2805 #endif
2806         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2807         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2808         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2809         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2810         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2811         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2812         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2813         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2814         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2815         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2816         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2817 #if !USE_SIT_FUNCTION
2818         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2819         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2820         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2821 #endif
2822 #undef SIT_ITEM
2823 };
2824 /* Constants below must match table above */
2825 enum {
2826 #if ENABLE_ASH_ALIAS
2827         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2828 #endif
2829         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2830         CNL_CNL_CNL_CNL                    , /*  2 */
2831         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2832         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2833         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2834         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2835         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2836         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2837         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2838         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2839         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2840         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2841         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2842         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2843 };
2844
2845 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2846  * caller must ensure proper cast on it if c is *char_ptr!
2847  */
2848 /* Values for syntax param */
2849 #define BASESYNTAX 0    /* not in quotes */
2850 #define DQSYNTAX   1    /* in double quotes */
2851 #define SQSYNTAX   2    /* in single quotes */
2852 #define ARISYNTAX  3    /* in arithmetic */
2853 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2854
2855 #if USE_SIT_FUNCTION
2856
2857 static int
2858 SIT(int c, int syntax)
2859 {
2860         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2861         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2862         /*
2863          * This causes '/' to be prepended with CTLESC in dquoted string,
2864          * making "./file"* treated incorrectly because we feed
2865          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2866          * The "homegrown" glob implementation is okay with that,
2867          * but glibc one isn't. With '/' always treated as CWORD,
2868          * both work fine.
2869          */
2870 # if ENABLE_ASH_ALIAS
2871         static const uint8_t syntax_index_table[] ALIGN1 = {
2872                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2873                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2874                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2875                 11, 3                           /* "}~" */
2876         };
2877 # else
2878         static const uint8_t syntax_index_table[] ALIGN1 = {
2879                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2880                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2881                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2882                 10, 2                           /* "}~" */
2883         };
2884 # endif
2885         const char *s;
2886         int indx;
2887
2888         if (c == PEOF)
2889                 return CENDFILE;
2890 # if ENABLE_ASH_ALIAS
2891         if (c == PEOA)
2892                 indx = 0;
2893         else
2894 # endif
2895         {
2896                 /* Cast is purely for paranoia here,
2897                  * just in case someone passed signed char to us */
2898                 if ((unsigned char)c >= CTL_FIRST
2899                  && (unsigned char)c <= CTL_LAST
2900                 ) {
2901                         return CCTL;
2902                 }
2903                 s = strchrnul(spec_symbls, c);
2904                 if (*s == '\0')
2905                         return CWORD;
2906                 indx = syntax_index_table[s - spec_symbls];
2907         }
2908         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2909 }
2910
2911 #else   /* !USE_SIT_FUNCTION */
2912
2913 static const uint8_t syntax_index_table[] ALIGN1 = {
2914         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2915         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2923         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2924         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2925         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2926         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2946         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2947         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2948         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2949         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2950         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2952         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2954         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2955         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2956         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2957         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2958         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2960         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2961         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2962 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2963         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2975         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2976         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2978         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2979         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2980         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3008         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3009         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3010         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3011         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3013         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3014         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3039         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3040         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3041         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3042         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3043         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3044         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3045         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3046         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3047         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3048         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3049         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3050         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3051         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3052         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3053         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3172         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3173 # if ENABLE_ASH_ALIAS
3174         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3175 # endif
3176 };
3177
3178 #if 1
3179 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3180 #else /* debug version, caught one signed char bug */
3181 # define SIT(c, syntax) \
3182         ({ \
3183                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3184                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3185                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3186                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3187                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3188         })
3189 #endif
3190
3191 #endif  /* !USE_SIT_FUNCTION */
3192
3193
3194 /* ============ Alias handling */
3195
3196 #if ENABLE_ASH_ALIAS
3197
3198 #define ALIASINUSE 1
3199 #define ALIASDEAD  2
3200
3201 struct alias {
3202         struct alias *next;
3203         char *name;
3204         char *val;
3205         int flag;
3206 };
3207
3208
3209 static struct alias **atab; // [ATABSIZE];
3210 #define INIT_G_alias() do { \
3211         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3212 } while (0)
3213
3214
3215 static struct alias **
3216 __lookupalias(const char *name)
3217 {
3218         unsigned int hashval;
3219         struct alias **app;
3220         const char *p;
3221         unsigned int ch;
3222
3223         p = name;
3224
3225         ch = (unsigned char)*p;
3226         hashval = ch << 4;
3227         while (ch) {
3228                 hashval += ch;
3229                 ch = (unsigned char)*++p;
3230         }
3231         app = &atab[hashval % ATABSIZE];
3232
3233         for (; *app; app = &(*app)->next) {
3234                 if (strcmp(name, (*app)->name) == 0) {
3235                         break;
3236                 }
3237         }
3238
3239         return app;
3240 }
3241
3242 static struct alias *
3243 lookupalias(const char *name, int check)
3244 {
3245         struct alias *ap = *__lookupalias(name);
3246
3247         if (check && ap && (ap->flag & ALIASINUSE))
3248                 return NULL;
3249         return ap;
3250 }
3251
3252 static struct alias *
3253 freealias(struct alias *ap)
3254 {
3255         struct alias *next;
3256
3257         if (ap->flag & ALIASINUSE) {
3258                 ap->flag |= ALIASDEAD;
3259                 return ap;
3260         }
3261
3262         next = ap->next;
3263         free(ap->name);
3264         free(ap->val);
3265         free(ap);
3266         return next;
3267 }
3268
3269 static void
3270 setalias(const char *name, const char *val)
3271 {
3272         struct alias *ap, **app;
3273
3274         app = __lookupalias(name);
3275         ap = *app;
3276         INT_OFF;
3277         if (ap) {
3278                 if (!(ap->flag & ALIASINUSE)) {
3279                         free(ap->val);
3280                 }
3281                 ap->val = ckstrdup(val);
3282                 ap->flag &= ~ALIASDEAD;
3283         } else {
3284                 /* not found */
3285                 ap = ckzalloc(sizeof(struct alias));
3286                 ap->name = ckstrdup(name);
3287                 ap->val = ckstrdup(val);
3288                 /*ap->flag = 0; - ckzalloc did it */
3289                 /*ap->next = NULL;*/
3290                 *app = ap;
3291         }
3292         INT_ON;
3293 }
3294
3295 static int
3296 unalias(const char *name)
3297 {
3298         struct alias **app;
3299
3300         app = __lookupalias(name);
3301
3302         if (*app) {
3303                 INT_OFF;
3304                 *app = freealias(*app);
3305                 INT_ON;
3306                 return 0;
3307         }
3308
3309         return 1;
3310 }
3311
3312 static void
3313 rmaliases(void)
3314 {
3315         struct alias *ap, **app;
3316         int i;
3317
3318         INT_OFF;
3319         for (i = 0; i < ATABSIZE; i++) {
3320                 app = &atab[i];
3321                 for (ap = *app; ap; ap = *app) {
3322                         *app = freealias(*app);
3323                         if (ap == *app) {
3324                                 app = &ap->next;
3325                         }
3326                 }
3327         }
3328         INT_ON;
3329 }
3330
3331 static void
3332 printalias(const struct alias *ap)
3333 {
3334         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3335 }
3336
3337 /*
3338  * TODO - sort output
3339  */
3340 static int FAST_FUNC
3341 aliascmd(int argc UNUSED_PARAM, char **argv)
3342 {
3343         char *n, *v;
3344         int ret = 0;
3345         struct alias *ap;
3346
3347         if (!argv[1]) {
3348                 int i;
3349
3350                 for (i = 0; i < ATABSIZE; i++) {
3351                         for (ap = atab[i]; ap; ap = ap->next) {
3352                                 printalias(ap);
3353                         }
3354                 }
3355                 return 0;
3356         }
3357         while ((n = *++argv) != NULL) {
3358                 v = strchr(n+1, '=');
3359                 if (v == NULL) { /* n+1: funny ksh stuff */
3360                         ap = *__lookupalias(n);
3361                         if (ap == NULL) {
3362                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3363                                 ret = 1;
3364                         } else
3365                                 printalias(ap);
3366                 } else {
3367                         *v++ = '\0';
3368                         setalias(n, v);
3369                 }
3370         }
3371
3372         return ret;
3373 }
3374
3375 static int FAST_FUNC
3376 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3377 {
3378         int i;
3379
3380         while (nextopt("a") != '\0') {
3381                 rmaliases();
3382                 return 0;
3383         }
3384         for (i = 0; *argptr; argptr++) {
3385                 if (unalias(*argptr)) {
3386                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3387                         i = 1;
3388                 }
3389         }
3390
3391         return i;
3392 }
3393
3394 #endif /* ASH_ALIAS */
3395
3396
3397 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3398 #define FORK_FG    0
3399 #define FORK_BG    1
3400 #define FORK_NOJOB 2
3401
3402 /* mode flags for showjob(s) */
3403 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3404 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3405 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3406 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3407
3408 /*
3409  * A job structure contains information about a job.  A job is either a
3410  * single process or a set of processes contained in a pipeline.  In the
3411  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3412  * array of pids.
3413  */
3414 struct procstat {
3415         pid_t   ps_pid;         /* process id */
3416         int     ps_status;      /* last process status from wait() */
3417         char    *ps_cmd;        /* text of command being run */
3418 };
3419
3420 struct job {
3421         struct procstat ps0;    /* status of process */
3422         struct procstat *ps;    /* status or processes when more than one */
3423 #if JOBS
3424         int stopstatus;         /* status of a stopped job */
3425 #endif
3426         unsigned nprocs;        /* number of processes */
3427
3428 #define JOBRUNNING      0       /* at least one proc running */
3429 #define JOBSTOPPED      1       /* all procs are stopped */
3430 #define JOBDONE         2       /* all procs are completed */
3431         unsigned
3432                 state: 8,
3433 #if JOBS
3434                 sigint: 1,      /* job was killed by SIGINT */
3435                 jobctl: 1,      /* job running under job control */
3436 #endif
3437                 waited: 1,      /* true if this entry has been waited for */
3438                 used: 1,        /* true if this entry is in used */
3439                 changed: 1;     /* true if status has changed */
3440         struct job *prev_job;   /* previous job */
3441 };
3442
3443 static struct job *makejob(/*union node *,*/ int);
3444 static int forkshell(struct job *, union node *, int);
3445 static int waitforjob(struct job *);
3446
3447 #if !JOBS
3448 enum { doing_jobctl = 0 };
3449 #define setjobctl(on) do {} while (0)
3450 #else
3451 static smallint doing_jobctl; //references:8
3452 static void setjobctl(int);
3453 #endif
3454
3455 /*
3456  * Ignore a signal.
3457  */
3458 static void
3459 ignoresig(int signo)
3460 {
3461         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3462         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3463                 /* No, need to do it */
3464                 signal(signo, SIG_IGN);
3465         }
3466         sigmode[signo - 1] = S_HARD_IGN;
3467 }
3468
3469 /*
3470  * Only one usage site - in setsignal()
3471  */
3472 static void
3473 signal_handler(int signo)
3474 {
3475         if (signo == SIGCHLD) {
3476                 got_sigchld = 1;
3477                 if (!trap[SIGCHLD])
3478                         return;
3479         }
3480
3481         gotsig[signo - 1] = 1;
3482         pending_sig = signo;
3483
3484         if (signo == SIGINT && !trap[SIGINT]) {
3485                 if (!suppress_int) {
3486                         pending_sig = 0;
3487                         raise_interrupt(); /* does not return */
3488                 }
3489                 pending_int = 1;
3490         }
3491 }
3492
3493 /*
3494  * Set the signal handler for the specified signal.  The routine figures
3495  * out what it should be set to.
3496  */
3497 static void
3498 setsignal(int signo)
3499 {
3500         char *t;
3501         char cur_act, new_act;
3502         struct sigaction act;
3503
3504         t = trap[signo];
3505         new_act = S_DFL;
3506         if (t != NULL) { /* trap for this sig is set */
3507                 new_act = S_CATCH;
3508                 if (t[0] == '\0') /* trap is "": ignore this sig */
3509                         new_act = S_IGN;
3510         }
3511
3512         if (rootshell && new_act == S_DFL) {
3513                 switch (signo) {
3514                 case SIGINT:
3515                         if (iflag || minusc || sflag == 0)
3516                                 new_act = S_CATCH;
3517                         break;
3518                 case SIGQUIT:
3519 #if DEBUG
3520                         if (debug)
3521                                 break;
3522 #endif
3523                         /* man bash:
3524                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3525                          * commands run by bash have signal handlers
3526                          * set to the values inherited by the shell
3527                          * from its parent". */
3528                         new_act = S_IGN;
3529                         break;
3530                 case SIGTERM:
3531                         if (iflag)
3532                                 new_act = S_IGN;
3533                         break;
3534 #if JOBS
3535                 case SIGTSTP:
3536                 case SIGTTOU:
3537                         if (mflag)
3538                                 new_act = S_IGN;
3539                         break;
3540 #endif
3541                 }
3542         }
3543 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3544 //whereas we have to restore it to what shell got on entry
3545 //from the parent. See comment above
3546
3547         if (signo == SIGCHLD)
3548                 new_act = S_CATCH;
3549
3550         t = &sigmode[signo - 1];
3551         cur_act = *t;
3552         if (cur_act == 0) {
3553                 /* current setting is not yet known */
3554                 if (sigaction(signo, NULL, &act)) {
3555                         /* pretend it worked; maybe we should give a warning,
3556                          * but other shells don't. We don't alter sigmode,
3557                          * so we retry every time.
3558                          * btw, in Linux it never fails. --vda */
3559                         return;
3560                 }
3561                 if (act.sa_handler == SIG_IGN) {
3562                         cur_act = S_HARD_IGN;
3563                         if (mflag
3564                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3565                         ) {
3566                                 cur_act = S_IGN;   /* don't hard ignore these */
3567                         }
3568                 }
3569         }
3570         if (cur_act == S_HARD_IGN || cur_act == new_act)
3571                 return;
3572
3573         act.sa_handler = SIG_DFL;
3574         switch (new_act) {
3575         case S_CATCH:
3576                 act.sa_handler = signal_handler;
3577                 break;
3578         case S_IGN:
3579                 act.sa_handler = SIG_IGN;
3580                 break;
3581         }
3582
3583         /* flags and mask matter only if !DFL and !IGN, but we do it
3584          * for all cases for more deterministic behavior:
3585          */
3586         act.sa_flags = 0;
3587         sigfillset(&act.sa_mask);
3588
3589         sigaction_set(signo, &act);
3590
3591         *t = new_act;
3592 }
3593
3594 /* mode flags for set_curjob */
3595 #define CUR_DELETE 2
3596 #define CUR_RUNNING 1
3597 #define CUR_STOPPED 0
3598
3599 #if JOBS
3600 /* pgrp of shell on invocation */
3601 static int initialpgrp; //references:2
3602 static int ttyfd = -1; //5
3603 #endif
3604 /* array of jobs */
3605 static struct job *jobtab; //5
3606 /* size of array */
3607 static unsigned njobs; //4
3608 /* current job */
3609 static struct job *curjob; //lots
3610 /* number of presumed living untracked jobs */
3611 static int jobless; //4
3612
3613 #if 0
3614 /* Bash has a feature: it restores termios after a successful wait for
3615  * a foreground job which had at least one stopped or sigkilled member.
3616  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3617  * properly restoring tty state. Should we do this too?
3618  * A reproducer: ^Z an interactive python:
3619  *
3620  * # python
3621  * Python 2.7.12 (...)
3622  * >>> ^Z
3623  *      { python leaves tty in -icanon -echo state. We do survive that... }
3624  *  [1]+  Stopped                    python
3625  *      { ...however, next program (python #2) does not survive it well: }
3626  * # python
3627  * Python 2.7.12 (...)
3628  * >>> Traceback (most recent call last):
3629  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3630  *   File "<stdin>", line 1, in <module>
3631  * NameError: name 'qwerty' is not defined
3632  *
3633  * The implementation below is modeled on bash code and seems to work.
3634  * However, I'm not sure we should do this. For one: what if I'd fg
3635  * the stopped python instead? It'll be confused by "restored" tty state.
3636  */
3637 static struct termios shell_tty_info;
3638 static void
3639 get_tty_state(void)
3640 {
3641         if (rootshell && ttyfd >= 0)
3642                 tcgetattr(ttyfd, &shell_tty_info);
3643 }
3644 static void
3645 set_tty_state(void)
3646 {
3647         /* if (rootshell) - caller ensures this */
3648         if (ttyfd >= 0)
3649                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3650 }
3651 static int
3652 job_signal_status(struct job *jp)
3653 {
3654         int status;
3655         unsigned i;
3656         struct procstat *ps = jp->ps;
3657         for (i = 0; i < jp->nprocs; i++) {
3658                 status = ps[i].ps_status;
3659                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3660                         return status;
3661         }
3662         return 0;
3663 }
3664 static void
3665 restore_tty_if_stopped_or_signaled(struct job *jp)
3666 {
3667 //TODO: check what happens if we come from waitforjob() in expbackq()
3668         if (rootshell) {
3669                 int s = job_signal_status(jp);
3670                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3671                         set_tty_state();
3672         }
3673 }
3674 #else
3675 # define get_tty_state() ((void)0)
3676 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3677 #endif
3678
3679 static void
3680 set_curjob(struct job *jp, unsigned mode)
3681 {
3682         struct job *jp1;
3683         struct job **jpp, **curp;
3684
3685         /* first remove from list */
3686         jpp = curp = &curjob;
3687         while (1) {
3688                 jp1 = *jpp;
3689                 if (jp1 == jp)
3690                         break;
3691                 jpp = &jp1->prev_job;
3692         }
3693         *jpp = jp1->prev_job;
3694
3695         /* Then re-insert in correct position */
3696         jpp = curp;
3697         switch (mode) {
3698         default:
3699 #if DEBUG
3700                 abort();
3701 #endif
3702         case CUR_DELETE:
3703                 /* job being deleted */
3704                 break;
3705         case CUR_RUNNING:
3706                 /* newly created job or backgrounded job,
3707                  * put after all stopped jobs.
3708                  */
3709                 while (1) {
3710                         jp1 = *jpp;
3711 #if JOBS
3712                         if (!jp1 || jp1->state != JOBSTOPPED)
3713 #endif
3714                                 break;
3715                         jpp = &jp1->prev_job;
3716                 }
3717                 /* FALLTHROUGH */
3718 #if JOBS
3719         case CUR_STOPPED:
3720 #endif
3721                 /* newly stopped job - becomes curjob */
3722                 jp->prev_job = *jpp;
3723                 *jpp = jp;
3724                 break;
3725         }
3726 }
3727
3728 #if JOBS || DEBUG
3729 static int
3730 jobno(const struct job *jp)
3731 {
3732         return jp - jobtab + 1;
3733 }
3734 #endif
3735
3736 /*
3737  * Convert a job name to a job structure.
3738  */
3739 #if !JOBS
3740 #define getjob(name, getctl) getjob(name)
3741 #endif
3742 static struct job *
3743 getjob(const char *name, int getctl)
3744 {
3745         struct job *jp;
3746         struct job *found;
3747         const char *err_msg = "%s: no such job";
3748         unsigned num;
3749         int c;
3750         const char *p;
3751         char *(*match)(const char *, const char *);
3752
3753         jp = curjob;
3754         p = name;
3755         if (!p)
3756                 goto currentjob;
3757
3758         if (*p != '%')
3759                 goto err;
3760
3761         c = *++p;
3762         if (!c)
3763                 goto currentjob;
3764
3765         if (!p[1]) {
3766                 if (c == '+' || c == '%') {
3767  currentjob:
3768                         err_msg = "No current job";
3769                         goto check;
3770                 }
3771                 if (c == '-') {
3772                         if (jp)
3773                                 jp = jp->prev_job;
3774                         err_msg = "No previous job";
3775  check:
3776                         if (!jp)
3777                                 goto err;
3778                         goto gotit;
3779                 }
3780         }
3781
3782         if (is_number(p)) {
3783                 num = atoi(p);
3784                 if (num > 0 && num <= njobs) {
3785                         jp = jobtab + num - 1;
3786                         if (jp->used)
3787                                 goto gotit;
3788                         goto err;
3789                 }
3790         }
3791
3792         match = prefix;
3793         if (*p == '?') {
3794                 match = strstr;
3795                 p++;
3796         }
3797
3798         found = NULL;
3799         while (jp) {
3800                 if (match(jp->ps[0].ps_cmd, p)) {
3801                         if (found)
3802                                 goto err;
3803                         found = jp;
3804                         err_msg = "%s: ambiguous";
3805                 }
3806                 jp = jp->prev_job;
3807         }
3808         if (!found)
3809                 goto err;
3810         jp = found;
3811
3812  gotit:
3813 #if JOBS
3814         err_msg = "job %s not created under job control";
3815         if (getctl && jp->jobctl == 0)
3816                 goto err;
3817 #endif
3818         return jp;
3819  err:
3820         ash_msg_and_raise_error(err_msg, name);
3821 }
3822
3823 /*
3824  * Mark a job structure as unused.
3825  */
3826 static void
3827 freejob(struct job *jp)
3828 {
3829         struct procstat *ps;
3830         int i;
3831
3832         INT_OFF;
3833         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3834                 if (ps->ps_cmd != nullstr)
3835                         free(ps->ps_cmd);
3836         }
3837         if (jp->ps != &jp->ps0)
3838                 free(jp->ps);
3839         jp->used = 0;
3840         set_curjob(jp, CUR_DELETE);
3841         INT_ON;
3842 }
3843
3844 #if JOBS
3845 static void
3846 xtcsetpgrp(int fd, pid_t pgrp)
3847 {
3848         if (tcsetpgrp(fd, pgrp))
3849                 ash_msg_and_raise_error("can't set tty process group (%m)");
3850 }
3851
3852 /*
3853  * Turn job control on and off.
3854  *
3855  * Note:  This code assumes that the third arg to ioctl is a character
3856  * pointer, which is true on Berkeley systems but not System V.  Since
3857  * System V doesn't have job control yet, this isn't a problem now.
3858  *
3859  * Called with interrupts off.
3860  */
3861 static void
3862 setjobctl(int on)
3863 {
3864         int fd;
3865         int pgrp;
3866
3867         if (on == doing_jobctl || rootshell == 0)
3868                 return;
3869         if (on) {
3870                 int ofd;
3871                 ofd = fd = open(_PATH_TTY, O_RDWR);
3872                 if (fd < 0) {
3873         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3874          * That sometimes helps to acquire controlling tty.
3875          * Obviously, a workaround for bugs when someone
3876          * failed to provide a controlling tty to bash! :) */
3877                         fd = 2;
3878                         while (!isatty(fd))
3879                                 if (--fd < 0)
3880                                         goto out;
3881                 }
3882                 /* fd is a tty at this point */
3883                 fd = fcntl(fd, F_DUPFD, 10);
3884                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3885                         close(ofd);
3886                 if (fd < 0)
3887                         goto out; /* F_DUPFD failed */
3888                 close_on_exec_on(fd);
3889                 while (1) { /* while we are in the background */
3890                         pgrp = tcgetpgrp(fd);
3891                         if (pgrp < 0) {
3892  out:
3893                                 ash_msg("can't access tty; job control turned off");
3894                                 mflag = on = 0;
3895                                 goto close;
3896                         }
3897                         if (pgrp == getpgrp())
3898                                 break;
3899                         killpg(0, SIGTTIN);
3900                 }
3901                 initialpgrp = pgrp;
3902
3903                 setsignal(SIGTSTP);
3904                 setsignal(SIGTTOU);
3905                 setsignal(SIGTTIN);
3906                 pgrp = rootpid;
3907                 setpgid(0, pgrp);
3908                 xtcsetpgrp(fd, pgrp);
3909         } else {
3910                 /* turning job control off */
3911                 fd = ttyfd;
3912                 pgrp = initialpgrp;
3913                 /* was xtcsetpgrp, but this can make exiting ash
3914                  * loop forever if pty is already deleted */
3915                 tcsetpgrp(fd, pgrp);
3916                 setpgid(0, pgrp);
3917                 setsignal(SIGTSTP);
3918                 setsignal(SIGTTOU);
3919                 setsignal(SIGTTIN);
3920  close:
3921                 if (fd >= 0)
3922                         close(fd);
3923                 fd = -1;
3924         }
3925         ttyfd = fd;
3926         doing_jobctl = on;
3927 }
3928
3929 static int FAST_FUNC
3930 killcmd(int argc, char **argv)
3931 {
3932         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3933                 int i = 1;
3934                 do {
3935                         if (argv[i][0] == '%') {
3936                                 /*
3937                                  * "kill %N" - job kill
3938                                  * Converting to pgrp / pid kill
3939                                  */
3940                                 struct job *jp;
3941                                 char *dst;
3942                                 int j, n;
3943
3944                                 jp = getjob(argv[i], 0);
3945                                 /*
3946                                  * In jobs started under job control, we signal
3947                                  * entire process group by kill -PGRP_ID.
3948                                  * This happens, f.e., in interactive shell.
3949                                  *
3950                                  * Otherwise, we signal each child via
3951                                  * kill PID1 PID2 PID3.
3952                                  * Testcases:
3953                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3954                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3955                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3956                                  */
3957                                 n = jp->nprocs; /* can't be 0 (I hope) */
3958                                 if (jp->jobctl)
3959                                         n = 1;
3960                                 dst = alloca(n * sizeof(int)*4);
3961                                 argv[i] = dst;
3962                                 for (j = 0; j < n; j++) {
3963                                         struct procstat *ps = &jp->ps[j];
3964                                         /* Skip non-running and not-stopped members
3965                                          * (i.e. dead members) of the job
3966                                          */
3967                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3968                                                 continue;
3969                                         /*
3970                                          * kill_main has matching code to expect
3971                                          * leading space. Needed to not confuse
3972                                          * negative pids with "kill -SIGNAL_NO" syntax
3973                                          */
3974                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3975                                 }
3976                                 *dst = '\0';
3977                         }
3978                 } while (argv[++i]);
3979         }
3980         return kill_main(argc, argv);
3981 }
3982
3983 static void
3984 showpipe(struct job *jp /*, FILE *out*/)
3985 {
3986         struct procstat *ps;
3987         struct procstat *psend;
3988
3989         psend = jp->ps + jp->nprocs;
3990         for (ps = jp->ps + 1; ps < psend; ps++)
3991                 printf(" | %s", ps->ps_cmd);
3992         newline_and_flush(stdout);
3993         flush_stdout_stderr();
3994 }
3995
3996
3997 static int
3998 restartjob(struct job *jp, int mode)
3999 {
4000         struct procstat *ps;
4001         int i;
4002         int status;
4003         pid_t pgid;
4004
4005         INT_OFF;
4006         if (jp->state == JOBDONE)
4007                 goto out;
4008         jp->state = JOBRUNNING;
4009         pgid = jp->ps[0].ps_pid;
4010         if (mode == FORK_FG) {
4011                 get_tty_state();
4012                 xtcsetpgrp(ttyfd, pgid);
4013         }
4014         killpg(pgid, SIGCONT);
4015         ps = jp->ps;
4016         i = jp->nprocs;
4017         do {
4018                 if (WIFSTOPPED(ps->ps_status)) {
4019                         ps->ps_status = -1;
4020                 }
4021                 ps++;
4022         } while (--i);
4023  out:
4024         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4025         INT_ON;
4026         return status;
4027 }
4028
4029 static int FAST_FUNC
4030 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4031 {
4032         struct job *jp;
4033         int mode;
4034         int retval;
4035
4036         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4037         nextopt(nullstr);
4038         argv = argptr;
4039         do {
4040                 jp = getjob(*argv, 1);
4041                 if (mode == FORK_BG) {
4042                         set_curjob(jp, CUR_RUNNING);
4043                         printf("[%d] ", jobno(jp));
4044                 }
4045                 out1str(jp->ps[0].ps_cmd);
4046                 showpipe(jp /*, stdout*/);
4047                 retval = restartjob(jp, mode);
4048         } while (*argv && *++argv);
4049         return retval;
4050 }
4051 #endif
4052
4053 static int
4054 sprint_status48(char *s, int status, int sigonly)
4055 {
4056         int col;
4057         int st;
4058
4059         col = 0;
4060         if (!WIFEXITED(status)) {
4061 #if JOBS
4062                 if (WIFSTOPPED(status))
4063                         st = WSTOPSIG(status);
4064                 else
4065 #endif
4066                         st = WTERMSIG(status);
4067                 if (sigonly) {
4068                         if (st == SIGINT || st == SIGPIPE)
4069                                 goto out;
4070 #if JOBS
4071                         if (WIFSTOPPED(status))
4072                                 goto out;
4073 #endif
4074                 }
4075                 st &= 0x7f;
4076 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4077                 col = fmtstr(s, 32, strsignal(st));
4078                 if (WCOREDUMP(status)) {
4079                         strcpy(s + col, " (core dumped)");
4080                         col += sizeof(" (core dumped)")-1;
4081                 }
4082         } else if (!sigonly) {
4083                 st = WEXITSTATUS(status);
4084                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4085         }
4086  out:
4087         return col;
4088 }
4089
4090 static int
4091 wait_block_or_sig(int *status)
4092 {
4093         int pid;
4094
4095         do {
4096                 sigset_t mask;
4097
4098                 /* Poll all children for changes in their state */
4099                 got_sigchld = 0;
4100                 /* if job control is active, accept stopped processes too */
4101                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4102                 if (pid != 0)
4103                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4104
4105                 /* Children exist, but none are ready. Sleep until interesting signal */
4106 #if 1
4107                 sigfillset(&mask);
4108                 sigprocmask(SIG_SETMASK, &mask, &mask);
4109                 while (!got_sigchld && !pending_sig)
4110                         sigsuspend(&mask);
4111                 sigprocmask(SIG_SETMASK, &mask, NULL);
4112 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4113                 while (!got_sigchld && !pending_sig)
4114                         pause();
4115 #endif
4116
4117                 /* If it was SIGCHLD, poll children again */
4118         } while (got_sigchld);
4119
4120         return pid;
4121 }
4122
4123 #define DOWAIT_NONBLOCK 0
4124 #define DOWAIT_BLOCK    1
4125 #define DOWAIT_BLOCK_OR_SIG 2
4126
4127 static int
4128 dowait(int block, struct job *job)
4129 {
4130         int pid;
4131         int status;
4132         struct job *jp;
4133         struct job *thisjob = NULL;
4134
4135         TRACE(("dowait(0x%x) called\n", block));
4136
4137         /* It's wrong to call waitpid() outside of INT_OFF region:
4138          * signal can arrive just after syscall return and handler can
4139          * longjmp away, losing stop/exit notification processing.
4140          * Thus, for "jobs" builtin, and for waiting for a fg job,
4141          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4142          *
4143          * However, for "wait" builtin it is wrong to simply call waitpid()
4144          * in INT_OFF region: "wait" needs to wait for any running job
4145          * to change state, but should exit on any trap too.
4146          * In INT_OFF region, a signal just before syscall entry can set
4147          * pending_sig variables, but we can't check them, and we would
4148          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4149          *
4150          * Because of this, we run inside INT_OFF, but use a special routine
4151          * which combines waitpid() and sigsuspend().
4152          * This is the reason why we need to have a handler for SIGCHLD:
4153          * SIG_DFL handler does not wake sigsuspend().
4154          */
4155         INT_OFF;
4156         if (block == DOWAIT_BLOCK_OR_SIG) {
4157                 pid = wait_block_or_sig(&status);
4158         } else {
4159                 int wait_flags = 0;
4160                 if (block == DOWAIT_NONBLOCK)
4161                         wait_flags = WNOHANG;
4162                 /* if job control is active, accept stopped processes too */
4163                 if (doing_jobctl)
4164                         wait_flags |= WUNTRACED;
4165                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4166                 pid = waitpid(-1, &status, wait_flags);
4167         }
4168         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4169                                 pid, status, errno, strerror(errno)));
4170         if (pid <= 0)
4171                 goto out;
4172
4173         thisjob = NULL;
4174         for (jp = curjob; jp; jp = jp->prev_job) {
4175                 int jobstate;
4176                 struct procstat *ps;
4177                 struct procstat *psend;
4178                 if (jp->state == JOBDONE)
4179                         continue;
4180                 jobstate = JOBDONE;
4181                 ps = jp->ps;
4182                 psend = ps + jp->nprocs;
4183                 do {
4184                         if (ps->ps_pid == pid) {
4185                                 TRACE(("Job %d: changing status of proc %d "
4186                                         "from 0x%x to 0x%x\n",
4187                                         jobno(jp), pid, ps->ps_status, status));
4188                                 ps->ps_status = status;
4189                                 thisjob = jp;
4190                         }
4191                         if (ps->ps_status == -1)
4192                                 jobstate = JOBRUNNING;
4193 #if JOBS
4194                         if (jobstate == JOBRUNNING)
4195                                 continue;
4196                         if (WIFSTOPPED(ps->ps_status)) {
4197                                 jp->stopstatus = ps->ps_status;
4198                                 jobstate = JOBSTOPPED;
4199                         }
4200 #endif
4201                 } while (++ps < psend);
4202                 if (!thisjob)
4203                         continue;
4204
4205                 /* Found the job where one of its processes changed its state.
4206                  * Is there at least one live and running process in this job? */
4207                 if (jobstate != JOBRUNNING) {
4208                         /* No. All live processes in the job are stopped
4209                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4210                          */
4211                         thisjob->changed = 1;
4212                         if (thisjob->state != jobstate) {
4213                                 TRACE(("Job %d: changing state from %d to %d\n",
4214                                         jobno(thisjob), thisjob->state, jobstate));
4215                                 thisjob->state = jobstate;
4216 #if JOBS
4217                                 if (jobstate == JOBSTOPPED)
4218                                         set_curjob(thisjob, CUR_STOPPED);
4219 #endif
4220                         }
4221                 }
4222                 goto out;
4223         }
4224         /* The process wasn't found in job list */
4225 #if JOBS
4226         if (!WIFSTOPPED(status))
4227                 jobless--;
4228 #endif
4229  out:
4230         INT_ON;
4231
4232         if (thisjob && thisjob == job) {
4233                 char s[48 + 1];
4234                 int len;
4235
4236                 len = sprint_status48(s, status, 1);
4237                 if (len) {
4238                         s[len] = '\n';
4239                         s[len + 1] = '\0';
4240                         out2str(s);
4241                 }
4242         }
4243         return pid;
4244 }
4245
4246 #if JOBS
4247 static void
4248 showjob(struct job *jp, int mode)
4249 {
4250         struct procstat *ps;
4251         struct procstat *psend;
4252         int col;
4253         int indent_col;
4254         char s[16 + 16 + 48];
4255         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4256
4257         ps = jp->ps;
4258
4259         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4260                 /* just output process (group) id of pipeline */
4261                 fprintf(out, "%d\n", ps->ps_pid);
4262                 return;
4263         }
4264
4265         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4266         indent_col = col;
4267
4268         if (jp == curjob)
4269                 s[col - 3] = '+';
4270         else if (curjob && jp == curjob->prev_job)
4271                 s[col - 3] = '-';
4272
4273         if (mode & SHOW_PIDS)
4274                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4275
4276         psend = ps + jp->nprocs;
4277
4278         if (jp->state == JOBRUNNING) {
4279                 strcpy(s + col, "Running");
4280                 col += sizeof("Running") - 1;
4281         } else {
4282                 int status = psend[-1].ps_status;
4283                 if (jp->state == JOBSTOPPED)
4284                         status = jp->stopstatus;
4285                 col += sprint_status48(s + col, status, 0);
4286         }
4287         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4288
4289         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4290          * or prints several "PID             | <cmdN>" lines,
4291          * depending on SHOW_PIDS bit.
4292          * We do not print status of individual processes
4293          * between PID and <cmdN>. bash does it, but not very well:
4294          * first line shows overall job status, not process status,
4295          * making it impossible to know 1st process status.
4296          */
4297         goto start;
4298         do {
4299                 /* for each process */
4300                 s[0] = '\0';
4301                 col = 33;
4302                 if (mode & SHOW_PIDS)
4303                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4304  start:
4305                 fprintf(out, "%s%*c%s%s",
4306                                 s,
4307                                 33 - col >= 0 ? 33 - col : 0, ' ',
4308                                 ps == jp->ps ? "" : "| ",
4309                                 ps->ps_cmd
4310                 );
4311         } while (++ps != psend);
4312         newline_and_flush(out);
4313
4314         jp->changed = 0;
4315
4316         if (jp->state == JOBDONE) {
4317                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4318                 freejob(jp);
4319         }
4320 }
4321
4322 /*
4323  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4324  * statuses have changed since the last call to showjobs.
4325  */
4326 static void
4327 showjobs(int mode)
4328 {
4329         struct job *jp;
4330
4331         TRACE(("showjobs(0x%x) called\n", mode));
4332
4333         /* Handle all finished jobs */
4334         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4335                 continue;
4336
4337         for (jp = curjob; jp; jp = jp->prev_job) {
4338                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4339                         showjob(jp, mode);
4340                 }
4341         }
4342 }
4343
4344 static int FAST_FUNC
4345 jobscmd(int argc UNUSED_PARAM, char **argv)
4346 {
4347         int mode, m;
4348
4349         mode = 0;
4350         while ((m = nextopt("lp")) != '\0') {
4351                 if (m == 'l')
4352                         mode |= SHOW_PIDS;
4353                 else
4354                         mode |= SHOW_ONLY_PGID;
4355         }
4356
4357         argv = argptr;
4358         if (*argv) {
4359                 do
4360                         showjob(getjob(*argv, 0), mode);
4361                 while (*++argv);
4362         } else {
4363                 showjobs(mode);
4364         }
4365
4366         return 0;
4367 }
4368 #endif /* JOBS */
4369
4370 /* Called only on finished or stopped jobs (no members are running) */
4371 static int
4372 getstatus(struct job *job)
4373 {
4374         int status;
4375         int retval;
4376         struct procstat *ps;
4377
4378         /* Fetch last member's status */
4379         ps = job->ps + job->nprocs - 1;
4380         status = ps->ps_status;
4381         if (pipefail) {
4382                 /* "set -o pipefail" mode: use last _nonzero_ status */
4383                 while (status == 0 && --ps >= job->ps)
4384                         status = ps->ps_status;
4385         }
4386
4387         retval = WEXITSTATUS(status);
4388         if (!WIFEXITED(status)) {
4389 #if JOBS
4390                 retval = WSTOPSIG(status);
4391                 if (!WIFSTOPPED(status))
4392 #endif
4393                 {
4394                         /* XXX: limits number of signals */
4395                         retval = WTERMSIG(status);
4396 #if JOBS
4397                         if (retval == SIGINT)
4398                                 job->sigint = 1;
4399 #endif
4400                 }
4401                 retval += 128;
4402         }
4403         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4404                 jobno(job), job->nprocs, status, retval));
4405         return retval;
4406 }
4407
4408 static int FAST_FUNC
4409 waitcmd(int argc UNUSED_PARAM, char **argv)
4410 {
4411         struct job *job;
4412         int retval;
4413         struct job *jp;
4414
4415         nextopt(nullstr);
4416         retval = 0;
4417
4418         argv = argptr;
4419         if (!*argv) {
4420                 /* wait for all jobs */
4421                 for (;;) {
4422                         jp = curjob;
4423                         while (1) {
4424                                 if (!jp) /* no running procs */
4425                                         goto ret;
4426                                 if (jp->state == JOBRUNNING)
4427                                         break;
4428                                 jp->waited = 1;
4429                                 jp = jp->prev_job;
4430                         }
4431         /* man bash:
4432          * "When bash is waiting for an asynchronous command via
4433          * the wait builtin, the reception of a signal for which a trap
4434          * has been set will cause the wait builtin to return immediately
4435          * with an exit status greater than 128, immediately after which
4436          * the trap is executed."
4437          */
4438                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4439         /* if child sends us a signal *and immediately exits*,
4440          * dowait() returns pid > 0. Check this case,
4441          * not "if (dowait() < 0)"!
4442          */
4443                         if (pending_sig)
4444                                 goto sigout;
4445                 }
4446         }
4447
4448         retval = 127;
4449         do {
4450                 if (**argv != '%') {
4451                         pid_t pid = number(*argv);
4452                         job = curjob;
4453                         while (1) {
4454                                 if (!job)
4455                                         goto repeat;
4456                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4457                                         break;
4458                                 job = job->prev_job;
4459                         }
4460                 } else {
4461                         job = getjob(*argv, 0);
4462                 }
4463                 /* loop until process terminated or stopped */
4464                 while (job->state == JOBRUNNING) {
4465                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4466                         if (pending_sig)
4467                                 goto sigout;
4468                 }
4469                 job->waited = 1;
4470                 retval = getstatus(job);
4471  repeat: ;
4472         } while (*++argv);
4473
4474  ret:
4475         return retval;
4476  sigout:
4477         retval = 128 + pending_sig;
4478         return retval;
4479 }
4480
4481 static struct job *
4482 growjobtab(void)
4483 {
4484         size_t len;
4485         ptrdiff_t offset;
4486         struct job *jp, *jq;
4487
4488         len = njobs * sizeof(*jp);
4489         jq = jobtab;
4490         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4491
4492         offset = (char *)jp - (char *)jq;
4493         if (offset) {
4494                 /* Relocate pointers */
4495                 size_t l = len;
4496
4497                 jq = (struct job *)((char *)jq + l);
4498                 while (l) {
4499                         l -= sizeof(*jp);
4500                         jq--;
4501 #define joff(p) ((struct job *)((char *)(p) + l))
4502 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4503                         if (joff(jp)->ps == &jq->ps0)
4504                                 jmove(joff(jp)->ps);
4505                         if (joff(jp)->prev_job)
4506                                 jmove(joff(jp)->prev_job);
4507                 }
4508                 if (curjob)
4509                         jmove(curjob);
4510 #undef joff
4511 #undef jmove
4512         }
4513
4514         njobs += 4;
4515         jobtab = jp;
4516         jp = (struct job *)((char *)jp + len);
4517         jq = jp + 3;
4518         do {
4519                 jq->used = 0;
4520         } while (--jq >= jp);
4521         return jp;
4522 }
4523
4524 /*
4525  * Return a new job structure.
4526  * Called with interrupts off.
4527  */
4528 static struct job *
4529 makejob(/*union node *node,*/ int nprocs)
4530 {
4531         int i;
4532         struct job *jp;
4533
4534         for (i = njobs, jp = jobtab; ; jp++) {
4535                 if (--i < 0) {
4536                         jp = growjobtab();
4537                         break;
4538                 }
4539                 if (jp->used == 0)
4540                         break;
4541                 if (jp->state != JOBDONE || !jp->waited)
4542                         continue;
4543 #if JOBS
4544                 if (doing_jobctl)
4545                         continue;
4546 #endif
4547                 freejob(jp);
4548                 break;
4549         }
4550         memset(jp, 0, sizeof(*jp));
4551 #if JOBS
4552         /* jp->jobctl is a bitfield.
4553          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4554         if (doing_jobctl)
4555                 jp->jobctl = 1;
4556 #endif
4557         jp->prev_job = curjob;
4558         curjob = jp;
4559         jp->used = 1;
4560         jp->ps = &jp->ps0;
4561         if (nprocs > 1) {
4562                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4563         }
4564         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4565                                 jobno(jp)));
4566         return jp;
4567 }
4568
4569 #if JOBS
4570 /*
4571  * Return a string identifying a command (to be printed by the
4572  * jobs command).
4573  */
4574 static char *cmdnextc;
4575
4576 static void
4577 cmdputs(const char *s)
4578 {
4579         static const char vstype[VSTYPE + 1][3] = {
4580                 "", "}", "-", "+", "?", "=",
4581                 "%", "%%", "#", "##"
4582                 IF_BASH_SUBSTR(, ":")
4583                 IF_BASH_PATTERN_SUBST(, "/", "//")
4584         };
4585
4586         const char *p, *str;
4587         char cc[2];
4588         char *nextc;
4589         unsigned char c;
4590         unsigned char subtype = 0;
4591         int quoted = 0;
4592
4593         cc[1] = '\0';
4594         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4595         p = s;
4596         while ((c = *p++) != '\0') {
4597                 str = NULL;
4598                 switch (c) {
4599                 case CTLESC:
4600                         c = *p++;
4601                         break;
4602                 case CTLVAR:
4603                         subtype = *p++;
4604                         if ((subtype & VSTYPE) == VSLENGTH)
4605                                 str = "${#";
4606                         else
4607                                 str = "${";
4608                         goto dostr;
4609                 case CTLENDVAR:
4610                         str = "\"}" + !(quoted & 1);
4611                         quoted >>= 1;
4612                         subtype = 0;
4613                         goto dostr;
4614                 case CTLBACKQ:
4615                         str = "$(...)";
4616                         goto dostr;
4617 #if ENABLE_FEATURE_SH_MATH
4618                 case CTLARI:
4619                         str = "$((";
4620                         goto dostr;
4621                 case CTLENDARI:
4622                         str = "))";
4623                         goto dostr;
4624 #endif
4625                 case CTLQUOTEMARK:
4626                         quoted ^= 1;
4627                         c = '"';
4628                         break;
4629                 case '=':
4630                         if (subtype == 0)
4631                                 break;
4632                         if ((subtype & VSTYPE) != VSNORMAL)
4633                                 quoted <<= 1;
4634                         str = vstype[subtype & VSTYPE];
4635                         if (subtype & VSNUL)
4636                                 c = ':';
4637                         else
4638                                 goto checkstr;
4639                         break;
4640                 case '\'':
4641                 case '\\':
4642                 case '"':
4643                 case '$':
4644                         /* These can only happen inside quotes */
4645                         cc[0] = c;
4646                         str = cc;
4647                         c = '\\';
4648                         break;
4649                 default:
4650                         break;
4651                 }
4652                 USTPUTC(c, nextc);
4653  checkstr:
4654                 if (!str)
4655                         continue;
4656  dostr:
4657                 while ((c = *str++) != '\0') {
4658                         USTPUTC(c, nextc);
4659                 }
4660         } /* while *p++ not NUL */
4661
4662         if (quoted & 1) {
4663                 USTPUTC('"', nextc);
4664         }
4665         *nextc = 0;
4666         cmdnextc = nextc;
4667 }
4668
4669 /* cmdtxt() and cmdlist() call each other */
4670 static void cmdtxt(union node *n);
4671
4672 static void
4673 cmdlist(union node *np, int sep)
4674 {
4675         for (; np; np = np->narg.next) {
4676                 if (!sep)
4677                         cmdputs(" ");
4678                 cmdtxt(np);
4679                 if (sep && np->narg.next)
4680                         cmdputs(" ");
4681         }
4682 }
4683
4684 static void
4685 cmdtxt(union node *n)
4686 {
4687         union node *np;
4688         struct nodelist *lp;
4689         const char *p;
4690
4691         if (!n)
4692                 return;
4693         switch (n->type) {
4694         default:
4695 #if DEBUG
4696                 abort();
4697 #endif
4698         case NPIPE:
4699                 lp = n->npipe.cmdlist;
4700                 for (;;) {
4701                         cmdtxt(lp->n);
4702                         lp = lp->next;
4703                         if (!lp)
4704                                 break;
4705                         cmdputs(" | ");
4706                 }
4707                 break;
4708         case NSEMI:
4709                 p = "; ";
4710                 goto binop;
4711         case NAND:
4712                 p = " && ";
4713                 goto binop;
4714         case NOR:
4715                 p = " || ";
4716  binop:
4717                 cmdtxt(n->nbinary.ch1);
4718                 cmdputs(p);
4719                 n = n->nbinary.ch2;
4720                 goto donode;
4721         case NREDIR:
4722         case NBACKGND:
4723                 n = n->nredir.n;
4724                 goto donode;
4725         case NNOT:
4726                 cmdputs("!");
4727                 n = n->nnot.com;
4728  donode:
4729                 cmdtxt(n);
4730                 break;
4731         case NIF:
4732                 cmdputs("if ");
4733                 cmdtxt(n->nif.test);
4734                 cmdputs("; then ");
4735                 if (n->nif.elsepart) {
4736                         cmdtxt(n->nif.ifpart);
4737                         cmdputs("; else ");
4738                         n = n->nif.elsepart;
4739                 } else {
4740                         n = n->nif.ifpart;
4741                 }
4742                 p = "; fi";
4743                 goto dotail;
4744         case NSUBSHELL:
4745                 cmdputs("(");
4746                 n = n->nredir.n;
4747                 p = ")";
4748                 goto dotail;
4749         case NWHILE:
4750                 p = "while ";
4751                 goto until;
4752         case NUNTIL:
4753                 p = "until ";
4754  until:
4755                 cmdputs(p);
4756                 cmdtxt(n->nbinary.ch1);
4757                 n = n->nbinary.ch2;
4758                 p = "; done";
4759  dodo:
4760                 cmdputs("; do ");
4761  dotail:
4762                 cmdtxt(n);
4763                 goto dotail2;
4764         case NFOR:
4765                 cmdputs("for ");
4766                 cmdputs(n->nfor.var);
4767                 cmdputs(" in ");
4768                 cmdlist(n->nfor.args, 1);
4769                 n = n->nfor.body;
4770                 p = "; done";
4771                 goto dodo;
4772         case NDEFUN:
4773                 cmdputs(n->narg.text);
4774                 p = "() { ... }";
4775                 goto dotail2;
4776         case NCMD:
4777                 cmdlist(n->ncmd.args, 1);
4778                 cmdlist(n->ncmd.redirect, 0);
4779                 break;
4780         case NARG:
4781                 p = n->narg.text;
4782  dotail2:
4783                 cmdputs(p);
4784                 break;
4785         case NHERE:
4786         case NXHERE:
4787                 p = "<<...";
4788                 goto dotail2;
4789         case NCASE:
4790                 cmdputs("case ");
4791                 cmdputs(n->ncase.expr->narg.text);
4792                 cmdputs(" in ");
4793                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4794                         cmdtxt(np->nclist.pattern);
4795                         cmdputs(") ");
4796                         cmdtxt(np->nclist.body);
4797                         cmdputs(";; ");
4798                 }
4799                 p = "esac";
4800                 goto dotail2;
4801         case NTO:
4802                 p = ">";
4803                 goto redir;
4804         case NCLOBBER:
4805                 p = ">|";
4806                 goto redir;
4807         case NAPPEND:
4808                 p = ">>";
4809                 goto redir;
4810 #if BASH_REDIR_OUTPUT
4811         case NTO2:
4812 #endif
4813         case NTOFD:
4814                 p = ">&";
4815                 goto redir;
4816         case NFROM:
4817                 p = "<";
4818                 goto redir;
4819         case NFROMFD:
4820                 p = "<&";
4821                 goto redir;
4822         case NFROMTO:
4823                 p = "<>";
4824  redir:
4825                 cmdputs(utoa(n->nfile.fd));
4826                 cmdputs(p);
4827                 if (n->type == NTOFD || n->type == NFROMFD) {
4828                         cmdputs(utoa(n->ndup.dupfd));
4829                         break;
4830                 }
4831                 n = n->nfile.fname;
4832                 goto donode;
4833         }
4834 }
4835
4836 static char *
4837 commandtext(union node *n)
4838 {
4839         char *name;
4840
4841         STARTSTACKSTR(cmdnextc);
4842         cmdtxt(n);
4843         name = stackblock();
4844         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4845         return ckstrdup(name);
4846 }
4847 #endif /* JOBS */
4848
4849 /*
4850  * Fork off a subshell.  If we are doing job control, give the subshell its
4851  * own process group.  Jp is a job structure that the job is to be added to.
4852  * N is the command that will be evaluated by the child.  Both jp and n may
4853  * be NULL.  The mode parameter can be one of the following:
4854  *      FORK_FG - Fork off a foreground process.
4855  *      FORK_BG - Fork off a background process.
4856  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4857  *                   process group even if job control is on.
4858  *
4859  * When job control is turned off, background processes have their standard
4860  * input redirected to /dev/null (except for the second and later processes
4861  * in a pipeline).
4862  *
4863  * Called with interrupts off.
4864  */
4865 /*
4866  * Clear traps on a fork.
4867  */
4868 static void
4869 clear_traps(void)
4870 {
4871         char **tp;
4872
4873         INT_OFF;
4874         for (tp = trap; tp < &trap[NSIG]; tp++) {
4875                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4876                         if (trap_ptr == trap)
4877                                 free(*tp);
4878                         /* else: it "belongs" to trap_ptr vector, don't free */
4879                         *tp = NULL;
4880                         if ((tp - trap) != 0)
4881                                 setsignal(tp - trap);
4882                 }
4883         }
4884         may_have_traps = 0;
4885         INT_ON;
4886 }
4887
4888 /* Lives far away from here, needed for forkchild */
4889 static void closescript(void);
4890
4891 /* Called after fork(), in child */
4892 /* jp and n are NULL when called by openhere() for heredoc support */
4893 static NOINLINE void
4894 forkchild(struct job *jp, union node *n, int mode)
4895 {
4896         int oldlvl;
4897
4898         TRACE(("Child shell %d\n", getpid()));
4899         oldlvl = shlvl;
4900         shlvl++;
4901
4902         /* man bash: "Non-builtin commands run by bash have signal handlers
4903          * set to the values inherited by the shell from its parent".
4904          * Do we do it correctly? */
4905
4906         closescript();
4907
4908         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4909          && n && n->type == NCMD        /* is it single cmd? */
4910         /* && n->ncmd.args->type == NARG - always true? */
4911          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4912          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4913         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4914         ) {
4915                 TRACE(("Trap hack\n"));
4916                 /* Awful hack for `trap` or $(trap).
4917                  *
4918                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4919                  * contains an example where "trap" is executed in a subshell:
4920                  *
4921                  * save_traps=$(trap)
4922                  * ...
4923                  * eval "$save_traps"
4924                  *
4925                  * Standard does not say that "trap" in subshell shall print
4926                  * parent shell's traps. It only says that its output
4927                  * must have suitable form, but then, in the above example
4928                  * (which is not supposed to be normative), it implies that.
4929                  *
4930                  * bash (and probably other shell) does implement it
4931                  * (traps are reset to defaults, but "trap" still shows them),
4932                  * but as a result, "trap" logic is hopelessly messed up:
4933                  *
4934                  * # trap
4935                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4936                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4937                  * # true | trap   <--- trap is in subshell - no output (ditto)
4938                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4939                  * trap -- 'echo Ho' SIGWINCH
4940                  * # echo `(trap)`         <--- in subshell in subshell - output
4941                  * trap -- 'echo Ho' SIGWINCH
4942                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4943                  * trap -- 'echo Ho' SIGWINCH
4944                  *
4945                  * The rules when to forget and when to not forget traps
4946                  * get really complex and nonsensical.
4947                  *
4948                  * Our solution: ONLY bare $(trap) or `trap` is special.
4949                  */
4950                 /* Save trap handler strings for trap builtin to print */
4951                 trap_ptr = xmemdup(trap, sizeof(trap));
4952                 /* Fall through into clearing traps */
4953         }
4954         clear_traps();
4955 #if JOBS
4956         /* do job control only in root shell */
4957         doing_jobctl = 0;
4958         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4959                 pid_t pgrp;
4960
4961                 if (jp->nprocs == 0)
4962                         pgrp = getpid();
4963                 else
4964                         pgrp = jp->ps[0].ps_pid;
4965                 /* this can fail because we are doing it in the parent also */
4966                 setpgid(0, pgrp);
4967                 if (mode == FORK_FG)
4968                         xtcsetpgrp(ttyfd, pgrp);
4969                 setsignal(SIGTSTP);
4970                 setsignal(SIGTTOU);
4971         } else
4972 #endif
4973         if (mode == FORK_BG) {
4974                 /* man bash: "When job control is not in effect,
4975                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4976                 ignoresig(SIGINT);
4977                 ignoresig(SIGQUIT);
4978                 if (jp->nprocs == 0) {
4979                         close(0);
4980                         if (open(bb_dev_null, O_RDONLY) != 0)
4981                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4982                 }
4983         }
4984         if (oldlvl == 0) {
4985                 if (iflag) { /* why if iflag only? */
4986                         setsignal(SIGINT);
4987                         setsignal(SIGTERM);
4988                 }
4989                 /* man bash:
4990                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4991                  * commands run by bash have signal handlers
4992                  * set to the values inherited by the shell
4993                  * from its parent".
4994                  * Take care of the second rule: */
4995                 setsignal(SIGQUIT);
4996         }
4997 #if JOBS
4998         if (n && n->type == NCMD
4999          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5000         ) {
5001                 TRACE(("Job hack\n"));
5002                 /* "jobs": we do not want to clear job list for it,
5003                  * instead we remove only _its_ own_ job from job list.
5004                  * This makes "jobs .... | cat" more useful.
5005                  */
5006                 freejob(curjob);
5007                 return;
5008         }
5009 #endif
5010         for (jp = curjob; jp; jp = jp->prev_job)
5011                 freejob(jp);
5012         jobless = 0;
5013 }
5014
5015 /* Called after fork(), in parent */
5016 #if !JOBS
5017 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5018 #endif
5019 static void
5020 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5021 {
5022         TRACE(("In parent shell: child = %d\n", pid));
5023         if (!jp) {
5024                 /* jp is NULL when called by openhere() for heredoc support */
5025                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5026                         continue;
5027                 jobless++;
5028                 return;
5029         }
5030 #if JOBS
5031         if (mode != FORK_NOJOB && jp->jobctl) {
5032                 int pgrp;
5033
5034                 if (jp->nprocs == 0)
5035                         pgrp = pid;
5036                 else
5037                         pgrp = jp->ps[0].ps_pid;
5038                 /* This can fail because we are doing it in the child also */
5039                 setpgid(pid, pgrp);
5040         }
5041 #endif
5042         if (mode == FORK_BG) {
5043                 backgndpid = pid;               /* set $! */
5044                 set_curjob(jp, CUR_RUNNING);
5045         }
5046         if (jp) {
5047                 struct procstat *ps = &jp->ps[jp->nprocs++];
5048                 ps->ps_pid = pid;
5049                 ps->ps_status = -1;
5050                 ps->ps_cmd = nullstr;
5051 #if JOBS
5052                 if (doing_jobctl && n)
5053                         ps->ps_cmd = commandtext(n);
5054 #endif
5055         }
5056 }
5057
5058 /* jp and n are NULL when called by openhere() for heredoc support */
5059 static int
5060 forkshell(struct job *jp, union node *n, int mode)
5061 {
5062         int pid;
5063
5064         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5065         pid = fork();
5066         if (pid < 0) {
5067                 TRACE(("Fork failed, errno=%d", errno));
5068                 if (jp)
5069                         freejob(jp);
5070                 ash_msg_and_raise_error("can't fork");
5071         }
5072         if (pid == 0) {
5073                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5074                 forkchild(jp, n, mode);
5075         } else {
5076                 forkparent(jp, n, mode, pid);
5077         }
5078         return pid;
5079 }
5080
5081 /*
5082  * Wait for job to finish.
5083  *
5084  * Under job control we have the problem that while a child process
5085  * is running interrupts generated by the user are sent to the child
5086  * but not to the shell.  This means that an infinite loop started by
5087  * an interactive user may be hard to kill.  With job control turned off,
5088  * an interactive user may place an interactive program inside a loop.
5089  * If the interactive program catches interrupts, the user doesn't want
5090  * these interrupts to also abort the loop.  The approach we take here
5091  * is to have the shell ignore interrupt signals while waiting for a
5092  * foreground process to terminate, and then send itself an interrupt
5093  * signal if the child process was terminated by an interrupt signal.
5094  * Unfortunately, some programs want to do a bit of cleanup and then
5095  * exit on interrupt; unless these processes terminate themselves by
5096  * sending a signal to themselves (instead of calling exit) they will
5097  * confuse this approach.
5098  *
5099  * Called with interrupts off.
5100  */
5101 static int
5102 waitforjob(struct job *jp)
5103 {
5104         int st;
5105
5106         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5107
5108         INT_OFF;
5109         while (jp->state == JOBRUNNING) {
5110                 /* In non-interactive shells, we _can_ get
5111                  * a keyboard signal here and be EINTRed,
5112                  * but we just loop back, waiting for command to complete.
5113                  *
5114                  * man bash:
5115                  * "If bash is waiting for a command to complete and receives
5116                  * a signal for which a trap has been set, the trap
5117                  * will not be executed until the command completes."
5118                  *
5119                  * Reality is that even if trap is not set, bash
5120                  * will not act on the signal until command completes.
5121                  * Try this. sleep5intoff.c:
5122                  * #include <signal.h>
5123                  * #include <unistd.h>
5124                  * int main() {
5125                  *         sigset_t set;
5126                  *         sigemptyset(&set);
5127                  *         sigaddset(&set, SIGINT);
5128                  *         sigaddset(&set, SIGQUIT);
5129                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5130                  *         sleep(5);
5131                  *         return 0;
5132                  * }
5133                  * $ bash -c './sleep5intoff; echo hi'
5134                  * ^C^C^C^C <--- pressing ^C once a second
5135                  * $ _
5136                  * $ bash -c './sleep5intoff; echo hi'
5137                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5138                  * $ _
5139                  */
5140                 dowait(DOWAIT_BLOCK, jp);
5141         }
5142         INT_ON;
5143
5144         st = getstatus(jp);
5145 #if JOBS
5146         if (jp->jobctl) {
5147                 xtcsetpgrp(ttyfd, rootpid);
5148                 restore_tty_if_stopped_or_signaled(jp);
5149
5150                 /*
5151                  * This is truly gross.
5152                  * If we're doing job control, then we did a TIOCSPGRP which
5153                  * caused us (the shell) to no longer be in the controlling
5154                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5155                  * intuit from the subprocess exit status whether a SIGINT
5156                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5157                  */
5158                 if (jp->sigint) /* TODO: do the same with all signals */
5159                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5160         }
5161         if (jp->state == JOBDONE)
5162 #endif
5163                 freejob(jp);
5164         return st;
5165 }
5166
5167 /*
5168  * return 1 if there are stopped jobs, otherwise 0
5169  */
5170 static int
5171 stoppedjobs(void)
5172 {
5173         struct job *jp;
5174         int retval;
5175
5176         retval = 0;
5177         if (job_warning)
5178                 goto out;
5179         jp = curjob;
5180         if (jp && jp->state == JOBSTOPPED) {
5181                 out2str("You have stopped jobs.\n");
5182                 job_warning = 2;
5183                 retval++;
5184         }
5185  out:
5186         return retval;
5187 }
5188
5189
5190 /*
5191  * Code for dealing with input/output redirection.
5192  */
5193
5194 #undef EMPTY
5195 #undef CLOSED
5196 #define EMPTY -2                /* marks an unused slot in redirtab */
5197 #define CLOSED -3               /* marks a slot of previously-closed fd */
5198
5199 /*
5200  * Open a file in noclobber mode.
5201  * The code was copied from bash.
5202  */
5203 static int
5204 noclobberopen(const char *fname)
5205 {
5206         int r, fd;
5207         struct stat finfo, finfo2;
5208
5209         /*
5210          * If the file exists and is a regular file, return an error
5211          * immediately.
5212          */
5213         r = stat(fname, &finfo);
5214         if (r == 0 && S_ISREG(finfo.st_mode)) {
5215                 errno = EEXIST;
5216                 return -1;
5217         }
5218
5219         /*
5220          * If the file was not present (r != 0), make sure we open it
5221          * exclusively so that if it is created before we open it, our open
5222          * will fail.  Make sure that we do not truncate an existing file.
5223          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5224          * file was not a regular file, we leave O_EXCL off.
5225          */
5226         if (r != 0)
5227                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5228         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5229
5230         /* If the open failed, return the file descriptor right away. */
5231         if (fd < 0)
5232                 return fd;
5233
5234         /*
5235          * OK, the open succeeded, but the file may have been changed from a
5236          * non-regular file to a regular file between the stat and the open.
5237          * We are assuming that the O_EXCL open handles the case where FILENAME
5238          * did not exist and is symlinked to an existing file between the stat
5239          * and open.
5240          */
5241
5242         /*
5243          * If we can open it and fstat the file descriptor, and neither check
5244          * revealed that it was a regular file, and the file has not been
5245          * replaced, return the file descriptor.
5246          */
5247         if (fstat(fd, &finfo2) == 0
5248          && !S_ISREG(finfo2.st_mode)
5249          && finfo.st_dev == finfo2.st_dev
5250          && finfo.st_ino == finfo2.st_ino
5251         ) {
5252                 return fd;
5253         }
5254
5255         /* The file has been replaced.  badness. */
5256         close(fd);
5257         errno = EEXIST;
5258         return -1;
5259 }
5260
5261 /*
5262  * Handle here documents.  Normally we fork off a process to write the
5263  * data to a pipe.  If the document is short, we can stuff the data in
5264  * the pipe without forking.
5265  */
5266 /* openhere needs this forward reference */
5267 static void expandhere(union node *arg, int fd);
5268 static int
5269 openhere(union node *redir)
5270 {
5271         int pip[2];
5272         size_t len = 0;
5273
5274         if (pipe(pip) < 0)
5275                 ash_msg_and_raise_error("pipe call failed");
5276         if (redir->type == NHERE) {
5277                 len = strlen(redir->nhere.doc->narg.text);
5278                 if (len <= PIPE_BUF) {
5279                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5280                         goto out;
5281                 }
5282         }
5283         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5284                 /* child */
5285                 close(pip[0]);
5286                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5287                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5288                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5289                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5290                 signal(SIGPIPE, SIG_DFL);
5291                 if (redir->type == NHERE)
5292                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5293                 else /* NXHERE */
5294                         expandhere(redir->nhere.doc, pip[1]);
5295                 _exit(EXIT_SUCCESS);
5296         }
5297  out:
5298         close(pip[1]);
5299         return pip[0];
5300 }
5301
5302 static int
5303 openredirect(union node *redir)
5304 {
5305         char *fname;
5306         int f;
5307
5308         switch (redir->nfile.type) {
5309 /* Can't happen, our single caller does this itself */
5310 //      case NTOFD:
5311 //      case NFROMFD:
5312 //              return -1;
5313         case NHERE:
5314         case NXHERE:
5315                 return openhere(redir);
5316         }
5317
5318         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5319          * allocated space. Do it only when we know it is safe.
5320          */
5321         fname = redir->nfile.expfname;
5322
5323         switch (redir->nfile.type) {
5324         default:
5325 #if DEBUG
5326                 abort();
5327 #endif
5328         case NFROM:
5329                 f = open(fname, O_RDONLY);
5330                 if (f < 0)
5331                         goto eopen;
5332                 break;
5333         case NFROMTO:
5334                 f = open(fname, O_RDWR|O_CREAT, 0666);
5335                 if (f < 0)
5336                         goto ecreate;
5337                 break;
5338         case NTO:
5339 #if BASH_REDIR_OUTPUT
5340         case NTO2:
5341 #endif
5342                 /* Take care of noclobber mode. */
5343                 if (Cflag) {
5344                         f = noclobberopen(fname);
5345                         if (f < 0)
5346                                 goto ecreate;
5347                         break;
5348                 }
5349                 /* FALLTHROUGH */
5350         case NCLOBBER:
5351                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5352                 if (f < 0)
5353                         goto ecreate;
5354                 break;
5355         case NAPPEND:
5356                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5357                 if (f < 0)
5358                         goto ecreate;
5359                 break;
5360         }
5361
5362         return f;
5363  ecreate:
5364         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5365  eopen:
5366         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5367 }
5368
5369 /*
5370  * Copy a file descriptor to be >= 10. Throws exception on error.
5371  */
5372 static int
5373 savefd(int from)
5374 {
5375         int newfd;
5376         int err;
5377
5378         newfd = fcntl(from, F_DUPFD, 10);
5379         err = newfd < 0 ? errno : 0;
5380         if (err != EBADF) {
5381                 if (err)
5382                         ash_msg_and_raise_error("%d: %m", from);
5383                 close(from);
5384                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5385         }
5386
5387         return newfd;
5388 }
5389 static int
5390 dup2_or_raise(int from, int to)
5391 {
5392         int newfd;
5393
5394         newfd = (from != to) ? dup2(from, to) : to;
5395         if (newfd < 0) {
5396                 /* Happens when source fd is not open: try "echo >&99" */
5397                 ash_msg_and_raise_error("%d: %m", from);
5398         }
5399         return newfd;
5400 }
5401
5402 /* Struct def and variable are moved down to the first usage site */
5403 struct two_fd_t {
5404         int orig, copy;
5405 };
5406 struct redirtab {
5407         struct redirtab *next;
5408         int pair_count;
5409         struct two_fd_t two_fd[];
5410 };
5411 #define redirlist (G_var.redirlist)
5412 enum {
5413         COPYFD_RESTORE = (int)~(INT_MAX),
5414 };
5415
5416 static int
5417 need_to_remember(struct redirtab *rp, int fd)
5418 {
5419         int i;
5420
5421         if (!rp) /* remembering was not requested */
5422                 return 0;
5423
5424         for (i = 0; i < rp->pair_count; i++) {
5425                 if (rp->two_fd[i].orig == fd) {
5426                         /* already remembered */
5427                         return 0;
5428                 }
5429         }
5430         return 1;
5431 }
5432
5433 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5434 static int
5435 is_hidden_fd(struct redirtab *rp, int fd)
5436 {
5437         int i;
5438         struct parsefile *pf;
5439
5440         if (fd == -1)
5441                 return 0;
5442         /* Check open scripts' fds */
5443         pf = g_parsefile;
5444         while (pf) {
5445                 /* We skip pf_fd == 0 case because of the following case:
5446                  * $ ash  # running ash interactively
5447                  * $ . ./script.sh
5448                  * and in script.sh: "exec 9>&0".
5449                  * Even though top-level pf_fd _is_ 0,
5450                  * it's still ok to use it: "read" builtin uses it,
5451                  * why should we cripple "exec" builtin?
5452                  */
5453                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5454                         return 1;
5455                 }
5456                 pf = pf->prev;
5457         }
5458
5459         if (!rp)
5460                 return 0;
5461         /* Check saved fds of redirects */
5462         fd |= COPYFD_RESTORE;
5463         for (i = 0; i < rp->pair_count; i++) {
5464                 if (rp->two_fd[i].copy == fd) {
5465                         return 1;
5466                 }
5467         }
5468         return 0;
5469 }
5470
5471 /*
5472  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5473  * old file descriptors are stashed away so that the redirection can be
5474  * undone by calling popredir.
5475  */
5476 /* flags passed to redirect */
5477 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5478 #define REDIR_SAVEFD2 03        /* set preverrout */
5479 static void
5480 redirect(union node *redir, int flags)
5481 {
5482         struct redirtab *sv;
5483         int sv_pos;
5484         int i;
5485         int fd;
5486         int newfd;
5487         int copied_fd2 = -1;
5488
5489         if (!redir) {
5490                 return;
5491         }
5492
5493         sv = NULL;
5494         sv_pos = 0;
5495         INT_OFF;
5496         if (flags & REDIR_PUSH) {
5497                 union node *tmp = redir;
5498                 do {
5499                         sv_pos++;
5500 #if BASH_REDIR_OUTPUT
5501                         if (tmp->nfile.type == NTO2)
5502                                 sv_pos++;
5503 #endif
5504                         tmp = tmp->nfile.next;
5505                 } while (tmp);
5506                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5507                 sv->next = redirlist;
5508                 sv->pair_count = sv_pos;
5509                 redirlist = sv;
5510                 while (sv_pos > 0) {
5511                         sv_pos--;
5512                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5513                 }
5514         }
5515
5516         do {
5517                 int right_fd = -1;
5518                 fd = redir->nfile.fd;
5519                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5520                         right_fd = redir->ndup.dupfd;
5521                         //bb_error_msg("doing %d > %d", fd, right_fd);
5522                         /* redirect from/to same file descriptor? */
5523                         if (right_fd == fd)
5524                                 continue;
5525                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5526                         if (is_hidden_fd(sv, right_fd)) {
5527                                 errno = EBADF; /* as if it is closed */
5528                                 ash_msg_and_raise_error("%d: %m", right_fd);
5529                         }
5530                         newfd = -1;
5531                 } else {
5532                         newfd = openredirect(redir); /* always >= 0 */
5533                         if (fd == newfd) {
5534                                 /* Descriptor wasn't open before redirect.
5535                                  * Mark it for close in the future */
5536                                 if (need_to_remember(sv, fd)) {
5537                                         goto remember_to_close;
5538                                 }
5539                                 continue;
5540                         }
5541                 }
5542 #if BASH_REDIR_OUTPUT
5543  redirect_more:
5544 #endif
5545                 if (need_to_remember(sv, fd)) {
5546                         /* Copy old descriptor */
5547                         /* Careful to not accidentally "save"
5548                          * to the same fd as right side fd in N>&M */
5549                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5550 #if defined(F_DUPFD_CLOEXEC)
5551                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5552 #else
5553                         i = fcntl(fd, F_DUPFD, minfd);
5554 #endif
5555                         if (i == -1) {
5556                                 i = errno;
5557                                 if (i != EBADF) {
5558                                         /* Strange error (e.g. "too many files" EMFILE?) */
5559                                         if (newfd >= 0)
5560                                                 close(newfd);
5561                                         errno = i;
5562                                         ash_msg_and_raise_error("%d: %m", fd);
5563                                         /* NOTREACHED */
5564                                 }
5565                                 /* EBADF: it is not open - good, remember to close it */
5566  remember_to_close:
5567                                 i = CLOSED;
5568                         } else { /* fd is open, save its copy */
5569 #if !defined(F_DUPFD_CLOEXEC)
5570                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5571 #endif
5572                                 /* "exec fd>&-" should not close fds
5573                                  * which point to script file(s).
5574                                  * Force them to be restored afterwards */
5575                                 if (is_hidden_fd(sv, fd))
5576                                         i |= COPYFD_RESTORE;
5577                         }
5578                         if (fd == 2)
5579                                 copied_fd2 = i;
5580                         sv->two_fd[sv_pos].orig = fd;
5581                         sv->two_fd[sv_pos].copy = i;
5582                         sv_pos++;
5583                 }
5584                 if (newfd < 0) {
5585                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5586                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5587                                 /* Don't want to trigger debugging */
5588                                 if (fd != -1)
5589                                         close(fd);
5590                         } else {
5591                                 dup2_or_raise(redir->ndup.dupfd, fd);
5592                         }
5593                 } else if (fd != newfd) { /* move newfd to fd */
5594                         dup2_or_raise(newfd, fd);
5595 #if BASH_REDIR_OUTPUT
5596                         if (!(redir->nfile.type == NTO2 && fd == 2))
5597 #endif
5598                                 close(newfd);
5599                 }
5600 #if BASH_REDIR_OUTPUT
5601                 if (redir->nfile.type == NTO2 && fd == 1) {
5602                         /* We already redirected it to fd 1, now copy it to 2 */
5603                         newfd = 1;
5604                         fd = 2;
5605                         goto redirect_more;
5606                 }
5607 #endif
5608         } while ((redir = redir->nfile.next) != NULL);
5609
5610         INT_ON;
5611         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5612                 preverrout_fd = copied_fd2;
5613 }
5614
5615 /*
5616  * Undo the effects of the last redirection.
5617  */
5618 static void
5619 popredir(int drop, int restore)
5620 {
5621         struct redirtab *rp;
5622         int i;
5623
5624         if (redirlist == NULL)
5625                 return;
5626         INT_OFF;
5627         rp = redirlist;
5628         for (i = 0; i < rp->pair_count; i++) {
5629                 int fd = rp->two_fd[i].orig;
5630                 int copy = rp->two_fd[i].copy;
5631                 if (copy == CLOSED) {
5632                         if (!drop)
5633                                 close(fd);
5634                         continue;
5635                 }
5636                 if (copy != EMPTY) {
5637                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5638                                 copy &= ~COPYFD_RESTORE;
5639                                 /*close(fd);*/
5640                                 dup2_or_raise(copy, fd);
5641                         }
5642                         close(copy & ~COPYFD_RESTORE);
5643                 }
5644         }
5645         redirlist = rp->next;
5646         free(rp);
5647         INT_ON;
5648 }
5649
5650 /*
5651  * Undo all redirections.  Called on error or interrupt.
5652  */
5653
5654 static int
5655 redirectsafe(union node *redir, int flags)
5656 {
5657         int err;
5658         volatile int saveint;
5659         struct jmploc *volatile savehandler = exception_handler;
5660         struct jmploc jmploc;
5661
5662         SAVE_INT(saveint);
5663         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5664         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5665         if (!err) {
5666                 exception_handler = &jmploc;
5667                 redirect(redir, flags);
5668         }
5669         exception_handler = savehandler;
5670         if (err && exception_type != EXERROR)
5671                 longjmp(exception_handler->loc, 1);
5672         RESTORE_INT(saveint);
5673         return err;
5674 }
5675
5676
5677 /* ============ Routines to expand arguments to commands
5678  *
5679  * We have to deal with backquotes, shell variables, and file metacharacters.
5680  */
5681
5682 #if ENABLE_FEATURE_SH_MATH
5683 static arith_t
5684 ash_arith(const char *s)
5685 {
5686         arith_state_t math_state;
5687         arith_t result;
5688
5689         math_state.lookupvar = lookupvar;
5690         math_state.setvar    = setvar0;
5691         //math_state.endofname = endofname;
5692
5693         INT_OFF;
5694         result = arith(&math_state, s);
5695         if (math_state.errmsg)
5696                 ash_msg_and_raise_error(math_state.errmsg);
5697         INT_ON;
5698
5699         return result;
5700 }
5701 #endif
5702
5703 /*
5704  * expandarg flags
5705  */
5706 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5707 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5708 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5709 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5710 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5711  * POSIX says for this case:
5712  *  Pathname expansion shall not be performed on the word by a
5713  *  non-interactive shell; an interactive shell may perform it, but shall
5714  *  do so only when the expansion would result in one word.
5715  * Currently, our code complies to the above rule by never globbing
5716  * redirection filenames.
5717  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5718  * (this means that on a typical Linux distro, bash almost always
5719  * performs globbing, and thus diverges from what we do).
5720  */
5721 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5722 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5723 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5724 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5725 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5726 /*
5727  * rmescape() flags
5728  */
5729 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5730 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5731 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5732 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5733 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5734
5735 /* Add CTLESC when necessary. */
5736 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5737 /* Do not skip NUL characters. */
5738 #define QUOTES_KEEPNUL EXP_TILDE
5739
5740 /*
5741  * Structure specifying which parts of the string should be searched
5742  * for IFS characters.
5743  */
5744 struct ifsregion {
5745         struct ifsregion *next; /* next region in list */
5746         int begoff;             /* offset of start of region */
5747         int endoff;             /* offset of end of region */
5748         int nulonly;            /* search for nul bytes only */
5749 };
5750
5751 struct arglist {
5752         struct strlist *list;
5753         struct strlist **lastp;
5754 };
5755
5756 /* output of current string */
5757 static char *expdest;
5758 /* list of back quote expressions */
5759 static struct nodelist *argbackq;
5760 /* first struct in list of ifs regions */
5761 static struct ifsregion ifsfirst;
5762 /* last struct in list */
5763 static struct ifsregion *ifslastp;
5764 /* holds expanded arg list */
5765 static struct arglist exparg;
5766
5767 /*
5768  * Our own itoa().
5769  */
5770 #if !ENABLE_FEATURE_SH_MATH
5771 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5772 typedef long arith_t;
5773 # define ARITH_FMT "%ld"
5774 #endif
5775 static int
5776 cvtnum(arith_t num)
5777 {
5778         int len;
5779
5780         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5781         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5782         STADJUST(len, expdest);
5783         return len;
5784 }
5785
5786 /*
5787  * Break the argument string into pieces based upon IFS and add the
5788  * strings to the argument list.  The regions of the string to be
5789  * searched for IFS characters have been stored by recordregion.
5790  */
5791 static void
5792 ifsbreakup(char *string, struct arglist *arglist)
5793 {
5794         struct ifsregion *ifsp;
5795         struct strlist *sp;
5796         char *start;
5797         char *p;
5798         char *q;
5799         const char *ifs, *realifs;
5800         int ifsspc;
5801         int nulonly;
5802
5803         start = string;
5804         if (ifslastp != NULL) {
5805                 ifsspc = 0;
5806                 nulonly = 0;
5807                 realifs = ifsset() ? ifsval() : defifs;
5808                 ifsp = &ifsfirst;
5809                 do {
5810                         p = string + ifsp->begoff;
5811                         nulonly = ifsp->nulonly;
5812                         ifs = nulonly ? nullstr : realifs;
5813                         ifsspc = 0;
5814                         while (p < string + ifsp->endoff) {
5815                                 q = p;
5816                                 if ((unsigned char)*p == CTLESC)
5817                                         p++;
5818                                 if (!strchr(ifs, *p)) {
5819                                         p++;
5820                                         continue;
5821                                 }
5822                                 if (!nulonly)
5823                                         ifsspc = (strchr(defifs, *p) != NULL);
5824                                 /* Ignore IFS whitespace at start */
5825                                 if (q == start && ifsspc) {
5826                                         p++;
5827                                         start = p;
5828                                         continue;
5829                                 }
5830                                 *q = '\0';
5831                                 sp = stzalloc(sizeof(*sp));
5832                                 sp->text = start;
5833                                 *arglist->lastp = sp;
5834                                 arglist->lastp = &sp->next;
5835                                 p++;
5836                                 if (!nulonly) {
5837                                         for (;;) {
5838                                                 if (p >= string + ifsp->endoff) {
5839                                                         break;
5840                                                 }
5841                                                 q = p;
5842                                                 if ((unsigned char)*p == CTLESC)
5843                                                         p++;
5844                                                 if (strchr(ifs, *p) == NULL) {
5845                                                         p = q;
5846                                                         break;
5847                                                 }
5848                                                 if (strchr(defifs, *p) == NULL) {
5849                                                         if (ifsspc) {
5850                                                                 p++;
5851                                                                 ifsspc = 0;
5852                                                         } else {
5853                                                                 p = q;
5854                                                                 break;
5855                                                         }
5856                                                 } else
5857                                                         p++;
5858                                         }
5859                                 }
5860                                 start = p;
5861                         } /* while */
5862                         ifsp = ifsp->next;
5863                 } while (ifsp != NULL);
5864                 if (nulonly)
5865                         goto add;
5866         }
5867
5868         if (!*start)
5869                 return;
5870
5871  add:
5872         sp = stzalloc(sizeof(*sp));
5873         sp->text = start;
5874         *arglist->lastp = sp;
5875         arglist->lastp = &sp->next;
5876 }
5877
5878 static void
5879 ifsfree(void)
5880 {
5881         struct ifsregion *p = ifsfirst.next;
5882
5883         if (!p)
5884                 goto out;
5885
5886         INT_OFF;
5887         do {
5888                 struct ifsregion *ifsp;
5889                 ifsp = p->next;
5890                 free(p);
5891                 p = ifsp;
5892         } while (p);
5893         ifsfirst.next = NULL;
5894         INT_ON;
5895  out:
5896         ifslastp = NULL;
5897 }
5898
5899 static size_t
5900 esclen(const char *start, const char *p)
5901 {
5902         size_t esc = 0;
5903
5904         while (p > start && (unsigned char)*--p == CTLESC) {
5905                 esc++;
5906         }
5907         return esc;
5908 }
5909
5910 /*
5911  * Remove any CTLESC characters from a string.
5912  */
5913 static char *
5914 rmescapes(char *str, int flag)
5915 {
5916         static const char qchars[] ALIGN1 = {
5917                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5918
5919         char *p, *q, *r;
5920         unsigned inquotes;
5921         unsigned protect_against_glob;
5922         unsigned globbing;
5923         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5924
5925         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5926         if (!p)
5927                 return str;
5928
5929         q = p;
5930         r = str;
5931         if (flag & RMESCAPE_ALLOC) {
5932                 size_t len = p - str;
5933                 size_t fulllen = len + strlen(p) + 1;
5934
5935                 if (flag & RMESCAPE_GROW) {
5936                         int strloc = str - (char *)stackblock();
5937                         r = makestrspace(fulllen, expdest);
5938                         /* p and str may be invalidated by makestrspace */
5939                         str = (char *)stackblock() + strloc;
5940                         p = str + len;
5941                 } else if (flag & RMESCAPE_HEAP) {
5942                         r = ckmalloc(fulllen);
5943                 } else {
5944                         r = stalloc(fulllen);
5945                 }
5946                 q = r;
5947                 if (len > 0) {
5948                         q = (char *)mempcpy(q, str, len);
5949                 }
5950         }
5951
5952         inquotes = 0;
5953         globbing = flag & RMESCAPE_GLOB;
5954         protect_against_glob = globbing;
5955         while (*p) {
5956                 if ((unsigned char)*p == CTLQUOTEMARK) {
5957 // Note: both inquotes and protect_against_glob only affect whether
5958 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5959                         inquotes = ~inquotes;
5960                         p++;
5961                         protect_against_glob = globbing;
5962                         continue;
5963                 }
5964                 if ((unsigned char)*p == CTLESC) {
5965                         p++;
5966 #if DEBUG
5967                         if (*p == '\0')
5968                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5969 #endif
5970                         if (protect_against_glob) {
5971                                 /*
5972                                  * We used to trust glob() and fnmatch() to eat
5973                                  * superfluous escapes (\z where z has no
5974                                  * special meaning anyway). But this causes
5975                                  * bugs such as string of one greek letter rho
5976                                  * (unicode-encoded as two bytes "cf,81")
5977                                  * getting encoded as "cf,CTLESC,81"
5978                                  * and here, converted to "cf,\,81" -
5979                                  * which does not go well with some flavors
5980                                  * of fnmatch() in unicode locales
5981                                  * (for example, glibc <= 2.22).
5982                                  *
5983                                  * Lets add "\" only on the chars which need it.
5984                                  * Testcases for less obvious chars are shown.
5985                                  */
5986                                 if (*p == '*'
5987                                  || *p == '?'
5988                                  || *p == '['
5989                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5990                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5991                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5992                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5993                                 /* Some libc support [^negate], that's why "^" also needs love */
5994                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5995                                 ) {
5996                                         *q++ = '\\';
5997                                 }
5998                         }
5999                 } else if (*p == '\\' && !inquotes) {
6000                         /* naked back slash */
6001                         protect_against_glob = 0;
6002                         goto copy;
6003                 }
6004 #if BASH_PATTERN_SUBST
6005                 else if (*p == '/' && slash) {
6006                         /* stop handling globbing and mark location of slash */
6007                         globbing = slash = 0;
6008                         *p = CTLESC;
6009                 }
6010 #endif
6011                 protect_against_glob = globbing;
6012  copy:
6013                 *q++ = *p++;
6014         }
6015         *q = '\0';
6016         if (flag & RMESCAPE_GROW) {
6017                 expdest = r;
6018                 STADJUST(q - r + 1, expdest);
6019         }
6020         return r;
6021 }
6022 #define pmatch(a, b) !fnmatch((a), (b), 0)
6023
6024 /*
6025  * Prepare a pattern for a expmeta (internal glob(3)) call.
6026  *
6027  * Returns an stalloced string.
6028  */
6029 static char *
6030 preglob(const char *pattern, int flag)
6031 {
6032         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6033 }
6034
6035 /*
6036  * Put a string on the stack.
6037  */
6038 static void
6039 memtodest(const char *p, size_t len, int syntax, int quotes)
6040 {
6041         char *q;
6042
6043         if (!len)
6044                 return;
6045
6046         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6047
6048         do {
6049                 unsigned char c = *p++;
6050                 if (c) {
6051                         if (quotes & QUOTES_ESC) {
6052                                 int n = SIT(c, syntax);
6053                                 if (n == CCTL
6054                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6055                                      && n == CBACK
6056                                     )
6057                                 ) {
6058                                         USTPUTC(CTLESC, q);
6059                                 }
6060                         }
6061                 } else if (!(quotes & QUOTES_KEEPNUL))
6062                         continue;
6063                 USTPUTC(c, q);
6064         } while (--len);
6065
6066         expdest = q;
6067 }
6068
6069 static size_t
6070 strtodest(const char *p, int syntax, int quotes)
6071 {
6072         size_t len = strlen(p);
6073         memtodest(p, len, syntax, quotes);
6074         return len;
6075 }
6076
6077 /*
6078  * Record the fact that we have to scan this region of the
6079  * string for IFS characters.
6080  */
6081 static void
6082 recordregion(int start, int end, int nulonly)
6083 {
6084         struct ifsregion *ifsp;
6085
6086         if (ifslastp == NULL) {
6087                 ifsp = &ifsfirst;
6088         } else {
6089                 INT_OFF;
6090                 ifsp = ckzalloc(sizeof(*ifsp));
6091                 /*ifsp->next = NULL; - ckzalloc did it */
6092                 ifslastp->next = ifsp;
6093                 INT_ON;
6094         }
6095         ifslastp = ifsp;
6096         ifslastp->begoff = start;
6097         ifslastp->endoff = end;
6098         ifslastp->nulonly = nulonly;
6099 }
6100
6101 static void
6102 removerecordregions(int endoff)
6103 {
6104         if (ifslastp == NULL)
6105                 return;
6106
6107         if (ifsfirst.endoff > endoff) {
6108                 while (ifsfirst.next) {
6109                         struct ifsregion *ifsp;
6110                         INT_OFF;
6111                         ifsp = ifsfirst.next->next;
6112                         free(ifsfirst.next);
6113                         ifsfirst.next = ifsp;
6114                         INT_ON;
6115                 }
6116                 if (ifsfirst.begoff > endoff) {
6117                         ifslastp = NULL;
6118                 } else {
6119                         ifslastp = &ifsfirst;
6120                         ifsfirst.endoff = endoff;
6121                 }
6122                 return;
6123         }
6124
6125         ifslastp = &ifsfirst;
6126         while (ifslastp->next && ifslastp->next->begoff < endoff)
6127                 ifslastp = ifslastp->next;
6128         while (ifslastp->next) {
6129                 struct ifsregion *ifsp;
6130                 INT_OFF;
6131                 ifsp = ifslastp->next->next;
6132                 free(ifslastp->next);
6133                 ifslastp->next = ifsp;
6134                 INT_ON;
6135         }
6136         if (ifslastp->endoff > endoff)
6137                 ifslastp->endoff = endoff;
6138 }
6139
6140 static char *
6141 exptilde(char *startp, char *p, int flags)
6142 {
6143         unsigned char c;
6144         char *name;
6145         struct passwd *pw;
6146         const char *home;
6147         int quotes = flags & QUOTES_ESC;
6148
6149         name = p + 1;
6150
6151         while ((c = *++p) != '\0') {
6152                 switch (c) {
6153                 case CTLESC:
6154                         return startp;
6155                 case CTLQUOTEMARK:
6156                         return startp;
6157                 case ':':
6158                         if (flags & EXP_VARTILDE)
6159                                 goto done;
6160                         break;
6161                 case '/':
6162                 case CTLENDVAR:
6163                         goto done;
6164                 }
6165         }
6166  done:
6167         *p = '\0';
6168         if (*name == '\0') {
6169                 home = lookupvar("HOME");
6170         } else {
6171                 pw = getpwnam(name);
6172                 if (pw == NULL)
6173                         goto lose;
6174                 home = pw->pw_dir;
6175         }
6176         if (!home || !*home)
6177                 goto lose;
6178         *p = c;
6179         strtodest(home, SQSYNTAX, quotes);
6180         return p;
6181  lose:
6182         *p = c;
6183         return startp;
6184 }
6185
6186 /*
6187  * Execute a command inside back quotes.  If it's a builtin command, we
6188  * want to save its output in a block obtained from malloc.  Otherwise
6189  * we fork off a subprocess and get the output of the command via a pipe.
6190  * Should be called with interrupts off.
6191  */
6192 struct backcmd {                /* result of evalbackcmd */
6193         int fd;                 /* file descriptor to read from */
6194         int nleft;              /* number of chars in buffer */
6195         char *buf;              /* buffer */
6196         struct job *jp;         /* job structure for command */
6197 };
6198
6199 /* These forward decls are needed to use "eval" code for backticks handling: */
6200 #define EV_EXIT 01              /* exit after evaluating tree */
6201 static int evaltree(union node *, int);
6202
6203 static void FAST_FUNC
6204 evalbackcmd(union node *n, struct backcmd *result)
6205 {
6206         int pip[2];
6207         struct job *jp;
6208
6209         result->fd = -1;
6210         result->buf = NULL;
6211         result->nleft = 0;
6212         result->jp = NULL;
6213         if (n == NULL) {
6214                 goto out;
6215         }
6216
6217         if (pipe(pip) < 0)
6218                 ash_msg_and_raise_error("pipe call failed");
6219         jp = makejob(/*n,*/ 1);
6220         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6221                 /* child */
6222                 FORCE_INT_ON;
6223                 close(pip[0]);
6224                 if (pip[1] != 1) {
6225                         /*close(1);*/
6226                         dup2_or_raise(pip[1], 1);
6227                         close(pip[1]);
6228                 }
6229 /* TODO: eflag clearing makes the following not abort:
6230  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6231  * which is what bash does (unless it is in POSIX mode).
6232  * dash deleted "eflag = 0" line in the commit
6233  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6234  *  [EVAL] Don't clear eflag in evalbackcmd
6235  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6236  */
6237                 eflag = 0;
6238                 ifsfree();
6239                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6240                 /* NOTREACHED */
6241         }
6242         /* parent */
6243         close(pip[1]);
6244         result->fd = pip[0];
6245         result->jp = jp;
6246
6247  out:
6248         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6249                 result->fd, result->buf, result->nleft, result->jp));
6250 }
6251
6252 /*
6253  * Expand stuff in backwards quotes.
6254  */
6255 static void
6256 expbackq(union node *cmd, int flag)
6257 {
6258         struct backcmd in;
6259         int i;
6260         char buf[128];
6261         char *p;
6262         char *dest;
6263         int startloc;
6264         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6265         struct stackmark smark;
6266
6267         INT_OFF;
6268         startloc = expdest - (char *)stackblock();
6269         pushstackmark(&smark, startloc);
6270         evalbackcmd(cmd, &in);
6271         popstackmark(&smark);
6272
6273         p = in.buf;
6274         i = in.nleft;
6275         if (i == 0)
6276                 goto read;
6277         for (;;) {
6278                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6279  read:
6280                 if (in.fd < 0)
6281                         break;
6282                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6283                 TRACE(("expbackq: read returns %d\n", i));
6284                 if (i <= 0)
6285                         break;
6286                 p = buf;
6287         }
6288
6289         free(in.buf);
6290         if (in.fd >= 0) {
6291                 close(in.fd);
6292                 back_exitstatus = waitforjob(in.jp);
6293         }
6294         INT_ON;
6295
6296         /* Eat all trailing newlines */
6297         dest = expdest;
6298         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6299                 STUNPUTC(dest);
6300         expdest = dest;
6301
6302         if (!(flag & EXP_QUOTED))
6303                 recordregion(startloc, dest - (char *)stackblock(), 0);
6304         TRACE(("evalbackq: size:%d:'%.*s'\n",
6305                 (int)((dest - (char *)stackblock()) - startloc),
6306                 (int)((dest - (char *)stackblock()) - startloc),
6307                 stackblock() + startloc));
6308 }
6309
6310 #if ENABLE_FEATURE_SH_MATH
6311 /*
6312  * Expand arithmetic expression.  Backup to start of expression,
6313  * evaluate, place result in (backed up) result, adjust string position.
6314  */
6315 static void
6316 expari(int flag)
6317 {
6318         char *p, *start;
6319         int begoff;
6320         int len;
6321
6322         /* ifsfree(); */
6323
6324         /*
6325          * This routine is slightly over-complicated for
6326          * efficiency.  Next we scan backwards looking for the
6327          * start of arithmetic.
6328          */
6329         start = stackblock();
6330         p = expdest - 1;
6331         *p = '\0';
6332         p--;
6333         while (1) {
6334                 int esc;
6335
6336                 while ((unsigned char)*p != CTLARI) {
6337                         p--;
6338 #if DEBUG
6339                         if (p < start) {
6340                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6341                         }
6342 #endif
6343                 }
6344
6345                 esc = esclen(start, p);
6346                 if (!(esc % 2)) {
6347                         break;
6348                 }
6349
6350                 p -= esc + 1;
6351         }
6352
6353         begoff = p - start;
6354
6355         removerecordregions(begoff);
6356
6357         expdest = p;
6358
6359         if (flag & QUOTES_ESC)
6360                 rmescapes(p + 1, 0);
6361
6362         len = cvtnum(ash_arith(p + 1));
6363
6364         if (!(flag & EXP_QUOTED))
6365                 recordregion(begoff, begoff + len, 0);
6366 }
6367 #endif
6368
6369 /* argstr needs it */
6370 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6371
6372 /*
6373  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6374  * characters to allow for further processing.  Otherwise treat
6375  * $@ like $* since no splitting will be performed.
6376  *
6377  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6378  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6379  * for correct expansion of "B=$A" word.
6380  */
6381 static void
6382 argstr(char *p, int flags, struct strlist *var_str_list)
6383 {
6384         static const char spclchars[] ALIGN1 = {
6385                 '=',
6386                 ':',
6387                 CTLQUOTEMARK,
6388                 CTLENDVAR,
6389                 CTLESC,
6390                 CTLVAR,
6391                 CTLBACKQ,
6392 #if ENABLE_FEATURE_SH_MATH
6393                 CTLENDARI,
6394 #endif
6395                 '\0'
6396         };
6397         const char *reject = spclchars;
6398         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6399         int inquotes;
6400         size_t length;
6401         int startloc;
6402
6403         if (!(flags & EXP_VARTILDE)) {
6404                 reject += 2;
6405         } else if (flags & EXP_VARTILDE2) {
6406                 reject++;
6407         }
6408         inquotes = 0;
6409         length = 0;
6410         if (flags & EXP_TILDE) {
6411                 char *q;
6412
6413                 flags &= ~EXP_TILDE;
6414  tilde:
6415                 q = p;
6416                 if (*q == '~')
6417                         p = exptilde(p, q, flags);
6418         }
6419  start:
6420         startloc = expdest - (char *)stackblock();
6421         for (;;) {
6422                 unsigned char c;
6423
6424                 length += strcspn(p + length, reject);
6425                 c = p[length];
6426                 if (c) {
6427                         if (!(c & 0x80)
6428                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6429                         ) {
6430                                 /* c == '=' || c == ':' || c == CTLENDARI */
6431                                 length++;
6432                         }
6433                 }
6434                 if (length > 0) {
6435                         int newloc;
6436                         expdest = stack_nputstr(p, length, expdest);
6437                         newloc = expdest - (char *)stackblock();
6438                         if (breakall && !inquotes && newloc > startloc) {
6439                                 recordregion(startloc, newloc, 0);
6440                         }
6441                         startloc = newloc;
6442                 }
6443                 p += length + 1;
6444                 length = 0;
6445
6446                 switch (c) {
6447                 case '\0':
6448                         goto breakloop;
6449                 case '=':
6450                         if (flags & EXP_VARTILDE2) {
6451                                 p--;
6452                                 continue;
6453                         }
6454                         flags |= EXP_VARTILDE2;
6455                         reject++;
6456                         /* fall through */
6457                 case ':':
6458                         /*
6459                          * sort of a hack - expand tildes in variable
6460                          * assignments (after the first '=' and after ':'s).
6461                          */
6462                         if (*--p == '~') {
6463                                 goto tilde;
6464                         }
6465                         continue;
6466                 }
6467
6468                 switch (c) {
6469                 case CTLENDVAR: /* ??? */
6470                         goto breakloop;
6471                 case CTLQUOTEMARK:
6472                         inquotes ^= EXP_QUOTED;
6473                         /* "$@" syntax adherence hack */
6474                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6475                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6476                                 goto start;
6477                         }
6478  addquote:
6479                         if (flags & QUOTES_ESC) {
6480                                 p--;
6481                                 length++;
6482                                 startloc++;
6483                         }
6484                         break;
6485                 case CTLESC:
6486                         startloc++;
6487                         length++;
6488
6489                         /*
6490                          * Quoted parameter expansion pattern: remove quote
6491                          * unless inside inner quotes or we have a literal
6492                          * backslash.
6493                          */
6494                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6495                             EXP_QPAT && *p != '\\')
6496                                 break;
6497
6498                         goto addquote;
6499                 case CTLVAR:
6500                         TRACE(("argstr: evalvar('%s')\n", p));
6501                         p = evalvar(p, flags | inquotes, var_str_list);
6502                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6503                         goto start;
6504                 case CTLBACKQ:
6505                         expbackq(argbackq->n, flags | inquotes);
6506                         argbackq = argbackq->next;
6507                         goto start;
6508 #if ENABLE_FEATURE_SH_MATH
6509                 case CTLENDARI:
6510                         p--;
6511                         expari(flags | inquotes);
6512                         goto start;
6513 #endif
6514                 }
6515         }
6516  breakloop: ;
6517 }
6518
6519 static char *
6520 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6521                 char *pattern, int quotes, int zero)
6522 {
6523         char *loc, *loc2;
6524         char c;
6525
6526         loc = startp;
6527         loc2 = rmesc;
6528         do {
6529                 int match;
6530                 const char *s = loc2;
6531
6532                 c = *loc2;
6533                 if (zero) {
6534                         *loc2 = '\0';
6535                         s = rmesc;
6536                 }
6537                 match = pmatch(pattern, s);
6538
6539                 *loc2 = c;
6540                 if (match)
6541                         return loc;
6542                 if (quotes && (unsigned char)*loc == CTLESC)
6543                         loc++;
6544                 loc++;
6545                 loc2++;
6546         } while (c);
6547         return NULL;
6548 }
6549
6550 static char *
6551 scanright(char *startp, char *rmesc, char *rmescend,
6552                 char *pattern, int quotes, int match_at_start)
6553 {
6554 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6555         int try2optimize = match_at_start;
6556 #endif
6557         int esc = 0;
6558         char *loc;
6559         char *loc2;
6560
6561         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6562          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6563          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6564          * Logic:
6565          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6566          * and on each iteration they go back two/one char until they reach the beginning.
6567          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6568          */
6569         /* TODO: document in what other circumstances we are called. */
6570
6571         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6572                 int match;
6573                 char c = *loc2;
6574                 const char *s = loc2;
6575                 if (match_at_start) {
6576                         *loc2 = '\0';
6577                         s = rmesc;
6578                 }
6579                 match = pmatch(pattern, s);
6580                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6581                 *loc2 = c;
6582                 if (match)
6583                         return loc;
6584 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6585                 if (try2optimize) {
6586                         /* Maybe we can optimize this:
6587                          * if pattern ends with unescaped *, we can avoid checking
6588                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6589                          * it won't match truncated "raw_value_of_" strings too.
6590                          */
6591                         unsigned plen = strlen(pattern);
6592                         /* Does it end with "*"? */
6593                         if (plen != 0 && pattern[--plen] == '*') {
6594                                 /* "xxxx*" is not escaped */
6595                                 /* "xxx\*" is escaped */
6596                                 /* "xx\\*" is not escaped */
6597                                 /* "x\\\*" is escaped */
6598                                 int slashes = 0;
6599                                 while (plen != 0 && pattern[--plen] == '\\')
6600                                         slashes++;
6601                                 if (!(slashes & 1))
6602                                         break; /* ends with unescaped "*" */
6603                         }
6604                         try2optimize = 0;
6605                 }
6606 #endif
6607                 loc--;
6608                 if (quotes) {
6609                         if (--esc < 0) {
6610                                 esc = esclen(startp, loc);
6611                         }
6612                         if (esc % 2) {
6613                                 esc--;
6614                                 loc--;
6615                         }
6616                 }
6617         }
6618         return NULL;
6619 }
6620
6621 static void varunset(const char *, const char *, const char *, int) NORETURN;
6622 static void
6623 varunset(const char *end, const char *var, const char *umsg, int varflags)
6624 {
6625         const char *msg;
6626         const char *tail;
6627
6628         tail = nullstr;
6629         msg = "parameter not set";
6630         if (umsg) {
6631                 if ((unsigned char)*end == CTLENDVAR) {
6632                         if (varflags & VSNUL)
6633                                 tail = " or null";
6634                 } else {
6635                         msg = umsg;
6636                 }
6637         }
6638         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6639 }
6640
6641 static const char *
6642 subevalvar(char *p, char *varname, int strloc, int subtype,
6643                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6644 {
6645         struct nodelist *saveargbackq = argbackq;
6646         int quotes = flag & QUOTES_ESC;
6647         char *startp;
6648         char *loc;
6649         char *rmesc, *rmescend;
6650         char *str;
6651         int amount, resetloc;
6652         IF_BASH_PATTERN_SUBST(int workloc;)
6653         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6654         int zero;
6655         char *(*scan)(char*, char*, char*, char*, int, int);
6656
6657         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6658         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6659
6660         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6661                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6662                         var_str_list);
6663         STPUTC('\0', expdest);
6664         argbackq = saveargbackq;
6665         startp = (char *)stackblock() + startloc;
6666
6667         switch (subtype) {
6668         case VSASSIGN:
6669                 setvar0(varname, startp);
6670                 amount = startp - expdest;
6671                 STADJUST(amount, expdest);
6672                 return startp;
6673
6674         case VSQUESTION:
6675                 varunset(p, varname, startp, varflags);
6676                 /* NOTREACHED */
6677
6678 #if BASH_SUBSTR
6679         case VSSUBSTR: {
6680                 int pos, len, orig_len;
6681                 char *colon;
6682
6683                 loc = str = stackblock() + strloc;
6684
6685 # if !ENABLE_FEATURE_SH_MATH
6686 #  define ash_arith number
6687 # endif
6688                 /* Read POS in ${var:POS:LEN} */
6689                 colon = strchr(loc, ':');
6690                 if (colon) *colon = '\0';
6691                 pos = ash_arith(loc);
6692                 if (colon) *colon = ':';
6693
6694                 /* Read LEN in ${var:POS:LEN} */
6695                 len = str - startp - 1;
6696                 /* *loc != '\0', guaranteed by parser */
6697                 if (quotes) {
6698                         char *ptr;
6699
6700                         /* Adjust the length by the number of escapes */
6701                         for (ptr = startp; ptr < (str - 1); ptr++) {
6702                                 if ((unsigned char)*ptr == CTLESC) {
6703                                         len--;
6704                                         ptr++;
6705                                 }
6706                         }
6707                 }
6708                 orig_len = len;
6709                 if (*loc++ == ':') {
6710                         /* ${var::LEN} */
6711                         len = ash_arith(loc);
6712                 } else {
6713                         /* Skip POS in ${var:POS:LEN} */
6714                         len = orig_len;
6715                         while (*loc && *loc != ':') {
6716                                 loc++;
6717                         }
6718                         if (*loc++ == ':') {
6719                                 len = ash_arith(loc);
6720                         }
6721                 }
6722 #  undef ash_arith
6723
6724                 if (pos < 0) {
6725                         /* ${VAR:$((-n)):l} starts n chars from the end */
6726                         pos = orig_len + pos;
6727                 }
6728                 if ((unsigned)pos >= orig_len) {
6729                         /* apart from obvious ${VAR:999999:l},
6730                          * covers ${VAR:$((-9999999)):l} - result is ""
6731                          * (bash compat)
6732                          */
6733                         pos = 0;
6734                         len = 0;
6735                 }
6736                 if (len < 0) {
6737                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6738                         len = (orig_len - pos) + len;
6739                 }
6740                 if ((unsigned)len > (orig_len - pos))
6741                         len = orig_len - pos;
6742
6743                 for (str = startp; pos; str++, pos--) {
6744                         if (quotes && (unsigned char)*str == CTLESC)
6745                                 str++;
6746                 }
6747                 for (loc = startp; len; len--) {
6748                         if (quotes && (unsigned char)*str == CTLESC)
6749                                 *loc++ = *str++;
6750                         *loc++ = *str++;
6751                 }
6752                 *loc = '\0';
6753                 amount = loc - expdest;
6754                 STADJUST(amount, expdest);
6755                 return loc;
6756         }
6757 #endif /* BASH_SUBSTR */
6758         }
6759
6760         resetloc = expdest - (char *)stackblock();
6761
6762 #if BASH_PATTERN_SUBST
6763         /* We'll comeback here if we grow the stack while handling
6764          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6765          * stack will need rebasing, and we'll need to remove our work
6766          * areas each time
6767          */
6768  restart:
6769 #endif
6770
6771         amount = expdest - ((char *)stackblock() + resetloc);
6772         STADJUST(-amount, expdest);
6773         startp = (char *)stackblock() + startloc;
6774
6775         rmesc = startp;
6776         rmescend = (char *)stackblock() + strloc;
6777         if (quotes) {
6778                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6779                 if (rmesc != startp) {
6780                         rmescend = expdest;
6781                         startp = (char *)stackblock() + startloc;
6782                 }
6783         }
6784         rmescend--;
6785         str = (char *)stackblock() + strloc;
6786         /*
6787          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6788          * The result is a_\_z_c (not a\_\_z_c)!
6789          *
6790          * The search pattern and replace string treat backslashes differently!
6791          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6792          * and string.  It's only used on the first call.
6793          */
6794         preglob(str, IF_BASH_PATTERN_SUBST(
6795                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6796                         RMESCAPE_SLASH : ) 0);
6797
6798 #if BASH_PATTERN_SUBST
6799         workloc = expdest - (char *)stackblock();
6800         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6801                 int len;
6802                 char *idx, *end;
6803
6804                 if (!repl) {
6805                         repl = strchr(str, CTLESC);
6806                         if (repl)
6807                                 *repl++ = '\0';
6808                         else
6809                                 repl = nullstr;
6810                 }
6811                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6812
6813                 /* If there's no pattern to match, return the expansion unmolested */
6814                 if (str[0] == '\0')
6815                         return NULL;
6816
6817                 len = 0;
6818                 idx = startp;
6819                 end = str - 1;
6820                 while (idx < end) {
6821  try_to_match:
6822                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6823                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6824                         if (!loc) {
6825                                 /* No match, advance */
6826                                 char *restart_detect = stackblock();
6827  skip_matching:
6828                                 STPUTC(*idx, expdest);
6829                                 if (quotes && (unsigned char)*idx == CTLESC) {
6830                                         idx++;
6831                                         len++;
6832                                         STPUTC(*idx, expdest);
6833                                 }
6834                                 if (stackblock() != restart_detect)
6835                                         goto restart;
6836                                 idx++;
6837                                 len++;
6838                                 rmesc++;
6839                                 /* continue; - prone to quadratic behavior, smarter code: */
6840                                 if (idx >= end)
6841                                         break;
6842                                 if (str[0] == '*') {
6843                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6844                                          * it would never match "ong_string" etc, no point in trying.
6845                                          */
6846                                         goto skip_matching;
6847                                 }
6848                                 goto try_to_match;
6849                         }
6850
6851                         if (subtype == VSREPLACEALL) {
6852                                 while (idx < loc) {
6853                                         if (quotes && (unsigned char)*idx == CTLESC)
6854                                                 idx++;
6855                                         idx++;
6856                                         rmesc++;
6857                                 }
6858                         } else {
6859                                 idx = loc;
6860                         }
6861
6862                         //bb_error_msg("repl:'%s'", repl);
6863                         for (loc = (char*)repl; *loc; loc++) {
6864                                 char *restart_detect = stackblock();
6865                                 if (quotes && *loc == '\\') {
6866                                         STPUTC(CTLESC, expdest);
6867                                         len++;
6868                                 }
6869                                 STPUTC(*loc, expdest);
6870                                 if (stackblock() != restart_detect)
6871                                         goto restart;
6872                                 len++;
6873                         }
6874
6875                         if (subtype == VSREPLACE) {
6876                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6877                                 while (*idx) {
6878                                         char *restart_detect = stackblock();
6879                                         STPUTC(*idx, expdest);
6880                                         if (stackblock() != restart_detect)
6881                                                 goto restart;
6882                                         len++;
6883                                         idx++;
6884                                 }
6885                                 break;
6886                         }
6887                 }
6888
6889                 /* We've put the replaced text into a buffer at workloc, now
6890                  * move it to the right place and adjust the stack.
6891                  */
6892                 STPUTC('\0', expdest);
6893                 startp = (char *)stackblock() + startloc;
6894                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6895                 //bb_error_msg("startp:'%s'", startp);
6896                 amount = expdest - (startp + len);
6897                 STADJUST(-amount, expdest);
6898                 return startp;
6899         }
6900 #endif /* BASH_PATTERN_SUBST */
6901
6902         subtype -= VSTRIMRIGHT;
6903 #if DEBUG
6904         if (subtype < 0 || subtype > 7)
6905                 abort();
6906 #endif
6907         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6908         zero = subtype >> 1;
6909         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6910         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6911
6912         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6913         if (loc) {
6914                 if (zero) {
6915                         memmove(startp, loc, str - loc);
6916                         loc = startp + (str - loc) - 1;
6917                 }
6918                 *loc = '\0';
6919                 amount = loc - expdest;
6920                 STADJUST(amount, expdest);
6921         }
6922         return loc;
6923 }
6924
6925 /*
6926  * Add the value of a specialized variable to the stack string.
6927  * name parameter (examples):
6928  * ash -c 'echo $1'      name:'1='
6929  * ash -c 'echo $qwe'    name:'qwe='
6930  * ash -c 'echo $$'      name:'$='
6931  * ash -c 'echo ${$}'    name:'$='
6932  * ash -c 'echo ${$##q}' name:'$=q'
6933  * ash -c 'echo ${#$}'   name:'$='
6934  * note: examples with bad shell syntax:
6935  * ash -c 'echo ${#$1}'  name:'$=1'
6936  * ash -c 'echo ${#1#}'  name:'1=#'
6937  */
6938 static NOINLINE ssize_t
6939 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6940 {
6941         const char *p;
6942         int num;
6943         int i;
6944         ssize_t len = 0;
6945         int sep;
6946         int quoted = *quotedp;
6947         int subtype = varflags & VSTYPE;
6948         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6949         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6950         int syntax;
6951
6952         sep = (flags & EXP_FULL) << CHAR_BIT;
6953         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6954
6955         switch (*name) {
6956         case '$':
6957                 num = rootpid;
6958                 goto numvar;
6959         case '?':
6960                 num = exitstatus;
6961                 goto numvar;
6962         case '#':
6963                 num = shellparam.nparam;
6964                 goto numvar;
6965         case '!':
6966                 num = backgndpid;
6967                 if (num == 0)
6968                         return -1;
6969  numvar:
6970                 len = cvtnum(num);
6971                 goto check_1char_name;
6972         case '-':
6973                 expdest = makestrspace(NOPTS, expdest);
6974                 for (i = NOPTS - 1; i >= 0; i--) {
6975                         if (optlist[i]) {
6976                                 USTPUTC(optletters(i), expdest);
6977                                 len++;
6978                         }
6979                 }
6980  check_1char_name:
6981 #if 0
6982                 /* handles cases similar to ${#$1} */
6983                 if (name[2] != '\0')
6984                         raise_error_syntax("bad substitution");
6985 #endif
6986                 break;
6987         case '@':
6988                 if (quoted && sep)
6989                         goto param;
6990                 /* fall through */
6991         case '*': {
6992                 char **ap;
6993                 char sepc;
6994
6995                 if (quoted)
6996                         sep = 0;
6997                 sep |= ifsset() ? ifsval()[0] : ' ';
6998  param:
6999                 sepc = sep;
7000                 *quotedp = !sepc;
7001                 ap = shellparam.p;
7002                 if (!ap)
7003                         return -1;
7004                 while ((p = *ap++) != NULL) {
7005                         len += strtodest(p, syntax, quotes);
7006
7007                         if (*ap && sep) {
7008                                 len++;
7009                                 memtodest(&sepc, 1, syntax, quotes);
7010                         }
7011                 }
7012                 break;
7013         } /* case '*' */
7014         case '0':
7015         case '1':
7016         case '2':
7017         case '3':
7018         case '4':
7019         case '5':
7020         case '6':
7021         case '7':
7022         case '8':
7023         case '9':
7024                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7025                 if (num < 0 || num > shellparam.nparam)
7026                         return -1;
7027                 p = num ? shellparam.p[num - 1] : arg0;
7028                 goto value;
7029         default:
7030                 /* NB: name has form "VAR=..." */
7031
7032                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
7033                  * which should be considered before we check variables. */
7034                 if (var_str_list) {
7035                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
7036                         p = NULL;
7037                         do {
7038                                 char *str, *eq;
7039                                 str = var_str_list->text;
7040                                 eq = strchr(str, '=');
7041                                 if (!eq) /* stop at first non-assignment */
7042                                         break;
7043                                 eq++;
7044                                 if (name_len == (unsigned)(eq - str)
7045                                  && strncmp(str, name, name_len) == 0
7046                                 ) {
7047                                         p = eq;
7048                                         /* goto value; - WRONG! */
7049                                         /* think "A=1 A=2 B=$A" */
7050                                 }
7051                                 var_str_list = var_str_list->next;
7052                         } while (var_str_list);
7053                         if (p)
7054                                 goto value;
7055                 }
7056                 p = lookupvar(name);
7057  value:
7058                 if (!p)
7059                         return -1;
7060
7061                 len = strtodest(p, syntax, quotes);
7062 #if ENABLE_UNICODE_SUPPORT
7063                 if (subtype == VSLENGTH && len > 0) {
7064                         reinit_unicode_for_ash();
7065                         if (unicode_status == UNICODE_ON) {
7066                                 STADJUST(-len, expdest);
7067                                 discard = 0;
7068                                 len = unicode_strlen(p);
7069                         }
7070                 }
7071 #endif
7072                 break;
7073         }
7074
7075         if (discard)
7076                 STADJUST(-len, expdest);
7077         return len;
7078 }
7079
7080 /*
7081  * Expand a variable, and return a pointer to the next character in the
7082  * input string.
7083  */
7084 static char *
7085 evalvar(char *p, int flag, struct strlist *var_str_list)
7086 {
7087         char varflags;
7088         char subtype;
7089         int quoted;
7090         char easy;
7091         char *var;
7092         int patloc;
7093         int startloc;
7094         ssize_t varlen;
7095
7096         varflags = (unsigned char) *p++;
7097         subtype = varflags & VSTYPE;
7098
7099         if (!subtype)
7100                 raise_error_syntax("bad substitution");
7101
7102         quoted = flag & EXP_QUOTED;
7103         var = p;
7104         easy = (!quoted || (*var == '@' && shellparam.nparam));
7105         startloc = expdest - (char *)stackblock();
7106         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7107
7108  again:
7109         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7110         if (varflags & VSNUL)
7111                 varlen--;
7112
7113         if (subtype == VSPLUS) {
7114                 varlen = -1 - varlen;
7115                 goto vsplus;
7116         }
7117
7118         if (subtype == VSMINUS) {
7119  vsplus:
7120                 if (varlen < 0) {
7121                         argstr(
7122                                 p,
7123                                 flag | EXP_TILDE | EXP_WORD,
7124                                 var_str_list
7125                         );
7126                         goto end;
7127                 }
7128                 goto record;
7129         }
7130
7131         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7132                 if (varlen >= 0)
7133                         goto record;
7134
7135                 subevalvar(p, var, 0, subtype, startloc, varflags,
7136                            flag & ~QUOTES_ESC, var_str_list);
7137                 varflags &= ~VSNUL;
7138                 /*
7139                  * Remove any recorded regions beyond
7140                  * start of variable
7141                  */
7142                 removerecordregions(startloc);
7143                 goto again;
7144         }
7145
7146         if (varlen < 0 && uflag)
7147                 varunset(p, var, 0, 0);
7148
7149         if (subtype == VSLENGTH) {
7150                 cvtnum(varlen > 0 ? varlen : 0);
7151                 goto record;
7152         }
7153
7154         if (subtype == VSNORMAL) {
7155  record:
7156                 if (!easy)
7157                         goto end;
7158                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7159                 goto end;
7160         }
7161
7162 #if DEBUG
7163         switch (subtype) {
7164         case VSTRIMLEFT:
7165         case VSTRIMLEFTMAX:
7166         case VSTRIMRIGHT:
7167         case VSTRIMRIGHTMAX:
7168 #if BASH_SUBSTR
7169         case VSSUBSTR:
7170 #endif
7171 #if BASH_PATTERN_SUBST
7172         case VSREPLACE:
7173         case VSREPLACEALL:
7174 #endif
7175                 break;
7176         default:
7177                 abort();
7178         }
7179 #endif
7180
7181         if (varlen >= 0) {
7182                 /*
7183                  * Terminate the string and start recording the pattern
7184                  * right after it
7185                  */
7186                 STPUTC('\0', expdest);
7187                 patloc = expdest - (char *)stackblock();
7188                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7189                                 startloc, varflags, flag, var_str_list)) {
7190                         int amount = expdest - (
7191                                 (char *)stackblock() + patloc - 1
7192                         );
7193                         STADJUST(-amount, expdest);
7194                 }
7195                 /* Remove any recorded regions beyond start of variable */
7196                 removerecordregions(startloc);
7197                 goto record;
7198         }
7199
7200  end:
7201         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7202                 int nesting = 1;
7203                 for (;;) {
7204                         unsigned char c = *p++;
7205                         if (c == CTLESC)
7206                                 p++;
7207                         else if (c == CTLBACKQ) {
7208                                 if (varlen >= 0)
7209                                         argbackq = argbackq->next;
7210                         } else if (c == CTLVAR) {
7211                                 if ((*p++ & VSTYPE) != VSNORMAL)
7212                                         nesting++;
7213                         } else if (c == CTLENDVAR) {
7214                                 if (--nesting == 0)
7215                                         break;
7216                         }
7217                 }
7218         }
7219         return p;
7220 }
7221
7222 /*
7223  * Add a file name to the list.
7224  */
7225 static void
7226 addfname(const char *name)
7227 {
7228         struct strlist *sp;
7229
7230         sp = stzalloc(sizeof(*sp));
7231         sp->text = sstrdup(name);
7232         *exparg.lastp = sp;
7233         exparg.lastp = &sp->next;
7234 }
7235
7236 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7237 static int
7238 hasmeta(const char *p)
7239 {
7240         static const char chars[] ALIGN1 = {
7241                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7242         };
7243
7244         for (;;) {
7245                 p = strpbrk(p, chars);
7246                 if (!p)
7247                         break;
7248                 switch ((unsigned char) *p) {
7249                 case CTLQUOTEMARK:
7250                         for (;;) {
7251                                 p++;
7252                                 if (*p == CTLQUOTEMARK)
7253                                         break;
7254                                 if (*p == CTLESC)
7255                                         p++;
7256                                 if (*p == '\0') /* huh? */
7257                                         return 0;
7258                         }
7259                         break;
7260                 case '\\':
7261                 case CTLESC:
7262                         p++;
7263                         if (*p == '\0')
7264                                 return 0;
7265                         break;
7266                 case '[':
7267                         if (!strchr(p + 1, ']')) {
7268                                 /* It's not a properly closed [] pattern,
7269                                  * but other metas may follow. Continue checking.
7270                                  * my[file* _is_ globbed by bash
7271                                  * and matches filenames like "my[file1".
7272                                  */
7273                                 break;
7274                         }
7275                         /* fallthrough */
7276                 default:
7277                 /* case '*': */
7278                 /* case '?': */
7279                         return 1;
7280                 }
7281                 p++;
7282         }
7283
7284         return 0;
7285 }
7286
7287 /* If we want to use glob() from libc... */
7288 #if !ENABLE_ASH_INTERNAL_GLOB
7289
7290 /* Add the result of glob() to the list */
7291 static void
7292 addglob(const glob_t *pglob)
7293 {
7294         char **p = pglob->gl_pathv;
7295
7296         do {
7297                 addfname(*p);
7298         } while (*++p);
7299 }
7300 static void
7301 expandmeta(struct strlist *str /*, int flag*/)
7302 {
7303         /* TODO - EXP_REDIR */
7304
7305         while (str) {
7306                 char *p;
7307                 glob_t pglob;
7308                 int i;
7309
7310                 if (fflag)
7311                         goto nometa;
7312
7313                 if (!hasmeta(str->text))
7314                         goto nometa;
7315
7316                 INT_OFF;
7317                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7318 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7319 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7320 //
7321 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7322 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7323 // Which means you need to unescape the string, right? Not so fast:
7324 // if there _is_ a file named "file\?" (with backslash), it is returned
7325 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7326 // You DON'T KNOW by looking at the result whether you need to unescape it.
7327 //
7328 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7329 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7330 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7331 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7332 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7333 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7334                 i = glob(p, 0, NULL, &pglob);
7335                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7336                 if (p != str->text)
7337                         free(p);
7338                 switch (i) {
7339                 case 0:
7340 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7341                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7342                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7343                                 goto nometa2;
7344 #endif
7345                         addglob(&pglob);
7346                         globfree(&pglob);
7347                         INT_ON;
7348                         break;
7349                 case GLOB_NOMATCH:
7350  //nometa2:
7351                         globfree(&pglob);
7352                         INT_ON;
7353  nometa:
7354                         *exparg.lastp = str;
7355                         rmescapes(str->text, 0);
7356                         exparg.lastp = &str->next;
7357                         break;
7358                 default:        /* GLOB_NOSPACE */
7359                         globfree(&pglob);
7360                         INT_ON;
7361                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7362                 }
7363                 str = str->next;
7364         }
7365 }
7366
7367 #else
7368 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7369
7370 /*
7371  * Do metacharacter (i.e. *, ?, [...]) expansion.
7372  */
7373 static void
7374 expmeta(char *expdir, char *enddir, char *name)
7375 {
7376         char *p;
7377         const char *cp;
7378         char *start;
7379         char *endname;
7380         int metaflag;
7381         struct stat statb;
7382         DIR *dirp;
7383         struct dirent *dp;
7384         int atend;
7385         int matchdot;
7386         int esc;
7387
7388         metaflag = 0;
7389         start = name;
7390         for (p = name; esc = 0, *p; p += esc + 1) {
7391                 if (*p == '*' || *p == '?')
7392                         metaflag = 1;
7393                 else if (*p == '[') {
7394                         char *q = p + 1;
7395                         if (*q == '!')
7396                                 q++;
7397                         for (;;) {
7398                                 if (*q == '\\')
7399                                         q++;
7400                                 if (*q == '/' || *q == '\0')
7401                                         break;
7402                                 if (*++q == ']') {
7403                                         metaflag = 1;
7404                                         break;
7405                                 }
7406                         }
7407                 } else {
7408                         if (*p == '\\')
7409                                 esc++;
7410                         if (p[esc] == '/') {
7411                                 if (metaflag)
7412                                         break;
7413                                 start = p + esc + 1;
7414                         }
7415                 }
7416         }
7417         if (metaflag == 0) {    /* we've reached the end of the file name */
7418                 if (enddir != expdir)
7419                         metaflag++;
7420                 p = name;
7421                 do {
7422                         if (*p == '\\')
7423                                 p++;
7424                         *enddir++ = *p;
7425                 } while (*p++);
7426                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7427                         addfname(expdir);
7428                 return;
7429         }
7430         endname = p;
7431         if (name < start) {
7432                 p = name;
7433                 do {
7434                         if (*p == '\\')
7435                                 p++;
7436                         *enddir++ = *p++;
7437                 } while (p < start);
7438         }
7439         if (enddir == expdir) {
7440                 cp = ".";
7441         } else if (enddir == expdir + 1 && *expdir == '/') {
7442                 cp = "/";
7443         } else {
7444                 cp = expdir;
7445                 enddir[-1] = '\0';
7446         }
7447         dirp = opendir(cp);
7448         if (dirp == NULL)
7449                 return;
7450         if (enddir != expdir)
7451                 enddir[-1] = '/';
7452         if (*endname == 0) {
7453                 atend = 1;
7454         } else {
7455                 atend = 0;
7456                 *endname = '\0';
7457                 endname += esc + 1;
7458         }
7459         matchdot = 0;
7460         p = start;
7461         if (*p == '\\')
7462                 p++;
7463         if (*p == '.')
7464                 matchdot++;
7465         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7466                 if (dp->d_name[0] == '.' && !matchdot)
7467                         continue;
7468                 if (pmatch(start, dp->d_name)) {
7469                         if (atend) {
7470                                 strcpy(enddir, dp->d_name);
7471                                 addfname(expdir);
7472                         } else {
7473                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7474                                         continue;
7475                                 p[-1] = '/';
7476                                 expmeta(expdir, p, endname);
7477                         }
7478                 }
7479         }
7480         closedir(dirp);
7481         if (!atend)
7482                 endname[-esc - 1] = esc ? '\\' : '/';
7483 }
7484
7485 static struct strlist *
7486 msort(struct strlist *list, int len)
7487 {
7488         struct strlist *p, *q = NULL;
7489         struct strlist **lpp;
7490         int half;
7491         int n;
7492
7493         if (len <= 1)
7494                 return list;
7495         half = len >> 1;
7496         p = list;
7497         for (n = half; --n >= 0;) {
7498                 q = p;
7499                 p = p->next;
7500         }
7501         q->next = NULL;                 /* terminate first half of list */
7502         q = msort(list, half);          /* sort first half of list */
7503         p = msort(p, len - half);               /* sort second half */
7504         lpp = &list;
7505         for (;;) {
7506 #if ENABLE_LOCALE_SUPPORT
7507                 if (strcoll(p->text, q->text) < 0)
7508 #else
7509                 if (strcmp(p->text, q->text) < 0)
7510 #endif
7511                                                 {
7512                         *lpp = p;
7513                         lpp = &p->next;
7514                         p = *lpp;
7515                         if (p == NULL) {
7516                                 *lpp = q;
7517                                 break;
7518                         }
7519                 } else {
7520                         *lpp = q;
7521                         lpp = &q->next;
7522                         q = *lpp;
7523                         if (q == NULL) {
7524                                 *lpp = p;
7525                                 break;
7526                         }
7527                 }
7528         }
7529         return list;
7530 }
7531
7532 /*
7533  * Sort the results of file name expansion.  It calculates the number of
7534  * strings to sort and then calls msort (short for merge sort) to do the
7535  * work.
7536  */
7537 static struct strlist *
7538 expsort(struct strlist *str)
7539 {
7540         int len;
7541         struct strlist *sp;
7542
7543         len = 0;
7544         for (sp = str; sp; sp = sp->next)
7545                 len++;
7546         return msort(str, len);
7547 }
7548
7549 static void
7550 expandmeta(struct strlist *str /*, int flag*/)
7551 {
7552         /* TODO - EXP_REDIR */
7553
7554         while (str) {
7555                 char *expdir;
7556                 struct strlist **savelastp;
7557                 struct strlist *sp;
7558                 char *p;
7559
7560                 if (fflag)
7561                         goto nometa;
7562                 if (!hasmeta(str->text))
7563                         goto nometa;
7564                 savelastp = exparg.lastp;
7565
7566                 INT_OFF;
7567                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7568                 {
7569                         int i = strlen(str->text);
7570 //BUGGY estimation of how long expanded name can be
7571                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7572                 }
7573                 expmeta(expdir, expdir, p);
7574                 free(expdir);
7575                 if (p != str->text)
7576                         free(p);
7577                 INT_ON;
7578                 if (exparg.lastp == savelastp) {
7579                         /*
7580                          * no matches
7581                          */
7582  nometa:
7583                         *exparg.lastp = str;
7584                         rmescapes(str->text, 0);
7585                         exparg.lastp = &str->next;
7586                 } else {
7587                         *exparg.lastp = NULL;
7588                         *savelastp = sp = expsort(*savelastp);
7589                         while (sp->next != NULL)
7590                                 sp = sp->next;
7591                         exparg.lastp = &sp->next;
7592                 }
7593                 str = str->next;
7594         }
7595 }
7596 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7597
7598 /*
7599  * Perform variable substitution and command substitution on an argument,
7600  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7601  * perform splitting and file name expansion.  When arglist is NULL, perform
7602  * here document expansion.
7603  */
7604 static void
7605 expandarg(union node *arg, struct arglist *arglist, int flag)
7606 {
7607         struct strlist *sp;
7608         char *p;
7609
7610         argbackq = arg->narg.backquote;
7611         STARTSTACKSTR(expdest);
7612         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7613         argstr(arg->narg.text, flag,
7614                         /* var_str_list: */ arglist ? arglist->list : NULL);
7615         p = _STPUTC('\0', expdest);
7616         expdest = p - 1;
7617         if (arglist == NULL) {
7618                 /* here document expanded */
7619                 goto out;
7620         }
7621         p = grabstackstr(p);
7622         TRACE(("expandarg: p:'%s'\n", p));
7623         exparg.lastp = &exparg.list;
7624         /*
7625          * TODO - EXP_REDIR
7626          */
7627         if (flag & EXP_FULL) {
7628                 ifsbreakup(p, &exparg);
7629                 *exparg.lastp = NULL;
7630                 exparg.lastp = &exparg.list;
7631                 expandmeta(exparg.list /*, flag*/);
7632         } else {
7633                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7634                         rmescapes(p, 0);
7635                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7636                 }
7637                 sp = stzalloc(sizeof(*sp));
7638                 sp->text = p;
7639                 *exparg.lastp = sp;
7640                 exparg.lastp = &sp->next;
7641         }
7642         *exparg.lastp = NULL;
7643         if (exparg.list) {
7644                 *arglist->lastp = exparg.list;
7645                 arglist->lastp = exparg.lastp;
7646         }
7647
7648  out:
7649         ifsfree();
7650 }
7651
7652 /*
7653  * Expand shell variables and backquotes inside a here document.
7654  */
7655 static void
7656 expandhere(union node *arg, int fd)
7657 {
7658         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7659         full_write(fd, stackblock(), expdest - (char *)stackblock());
7660 }
7661
7662 /*
7663  * Returns true if the pattern matches the string.
7664  */
7665 static int
7666 patmatch(char *pattern, const char *string)
7667 {
7668         char *p = preglob(pattern, 0);
7669         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7670         return pmatch(p, string);
7671 }
7672
7673 /*
7674  * See if a pattern matches in a case statement.
7675  */
7676 static int
7677 casematch(union node *pattern, char *val)
7678 {
7679         struct stackmark smark;
7680         int result;
7681
7682         setstackmark(&smark);
7683         argbackq = pattern->narg.backquote;
7684         STARTSTACKSTR(expdest);
7685         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7686                         /* var_str_list: */ NULL);
7687         STACKSTRNUL(expdest);
7688         ifsfree();
7689         result = patmatch(stackblock(), val);
7690         popstackmark(&smark);
7691         return result;
7692 }
7693
7694
7695 /* ============ find_command */
7696
7697 struct builtincmd {
7698         const char *name;
7699         int (*builtin)(int, char **) FAST_FUNC;
7700         /* unsigned flags; */
7701 };
7702 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7703 /* "regular" builtins always take precedence over commands,
7704  * regardless of PATH=....%builtin... position */
7705 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7706 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7707
7708 struct cmdentry {
7709         smallint cmdtype;       /* CMDxxx */
7710         union param {
7711                 int index;
7712                 /* index >= 0 for commands without path (slashes) */
7713                 /* (TODO: what exactly does the value mean? PATH position?) */
7714                 /* index == -1 for commands with slashes */
7715                 /* index == (-2 - applet_no) for NOFORK applets */
7716                 const struct builtincmd *cmd;
7717                 struct funcnode *func;
7718         } u;
7719 };
7720 /* values of cmdtype */
7721 #define CMDUNKNOWN      -1      /* no entry in table for command */
7722 #define CMDNORMAL       0       /* command is an executable program */
7723 #define CMDFUNCTION     1       /* command is a shell function */
7724 #define CMDBUILTIN      2       /* command is a shell builtin */
7725
7726 /* action to find_command() */
7727 #define DO_ERR          0x01    /* prints errors */
7728 #define DO_ABS          0x02    /* checks absolute paths */
7729 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7730 #define DO_ALTPATH      0x08    /* using alternate path */
7731 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7732
7733 static void find_command(char *, struct cmdentry *, int, const char *);
7734
7735
7736 /* ============ Hashing commands */
7737
7738 /*
7739  * When commands are first encountered, they are entered in a hash table.
7740  * This ensures that a full path search will not have to be done for them
7741  * on each invocation.
7742  *
7743  * We should investigate converting to a linear search, even though that
7744  * would make the command name "hash" a misnomer.
7745  */
7746
7747 struct tblentry {
7748         struct tblentry *next;  /* next entry in hash chain */
7749         union param param;      /* definition of builtin function */
7750         smallint cmdtype;       /* CMDxxx */
7751         char rehash;            /* if set, cd done since entry created */
7752         char cmdname[1];        /* name of command */
7753 };
7754
7755 static struct tblentry **cmdtable;
7756 #define INIT_G_cmdtable() do { \
7757         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7758 } while (0)
7759
7760 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7761
7762
7763 static void
7764 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7765 {
7766 #if ENABLE_FEATURE_SH_STANDALONE
7767         if (applet_no >= 0) {
7768                 if (APPLET_IS_NOEXEC(applet_no)) {
7769                         clearenv();
7770                         while (*envp)
7771                                 putenv(*envp++);
7772                         run_applet_no_and_exit(applet_no, cmd, argv);
7773                 }
7774                 /* re-exec ourselves with the new arguments */
7775                 execve(bb_busybox_exec_path, argv, envp);
7776                 /* If they called chroot or otherwise made the binary no longer
7777                  * executable, fall through */
7778         }
7779 #endif
7780
7781  repeat:
7782 #ifdef SYSV
7783         do {
7784                 execve(cmd, argv, envp);
7785         } while (errno == EINTR);
7786 #else
7787         execve(cmd, argv, envp);
7788 #endif
7789         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7790                 /* Run "cmd" as a shell script:
7791                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7792                  * "If the execve() function fails with ENOEXEC, the shell
7793                  * shall execute a command equivalent to having a shell invoked
7794                  * with the command name as its first operand,
7795                  * with any remaining arguments passed to the new shell"
7796                  *
7797                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7798                  * just call ourselves.
7799                  *
7800                  * Note that bash reads ~80 chars of the file, and if it sees
7801                  * a zero byte before it sees newline, it doesn't try to
7802                  * interpret it, but fails with "cannot execute binary file"
7803                  * message and exit code 126. For one, this prevents attempts
7804                  * to interpret foreign ELF binaries as shell scripts.
7805                  */
7806                 argv[0] = cmd;
7807                 cmd = (char*) bb_busybox_exec_path;
7808                 /* NB: this is only possible because all callers of shellexec()
7809                  * ensure that the argv[-1] slot exists!
7810                  */
7811                 argv--;
7812                 argv[0] = (char*) "ash";
7813                 goto repeat;
7814         }
7815 }
7816
7817 /*
7818  * Exec a program.  Never returns.  If you change this routine, you may
7819  * have to change the find_command routine as well.
7820  * argv[-1] must exist and be writable! See tryexec() for why.
7821  */
7822 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7823 static void shellexec(char *prog, char **argv, const char *path, int idx)
7824 {
7825         char *cmdname;
7826         int e;
7827         char **envp;
7828         int exerrno;
7829         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7830
7831         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7832         if (strchr(prog, '/') != NULL
7833 #if ENABLE_FEATURE_SH_STANDALONE
7834          || (applet_no = find_applet_by_name(prog)) >= 0
7835 #endif
7836         ) {
7837                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7838                 if (applet_no >= 0) {
7839                         /* We tried execing ourself, but it didn't work.
7840                          * Maybe /proc/self/exe doesn't exist?
7841                          * Try $PATH search.
7842                          */
7843                         goto try_PATH;
7844                 }
7845                 e = errno;
7846         } else {
7847  try_PATH:
7848                 e = ENOENT;
7849                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7850                         if (--idx < 0 && pathopt == NULL) {
7851                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7852                                 if (errno != ENOENT && errno != ENOTDIR)
7853                                         e = errno;
7854                         }
7855                         stunalloc(cmdname);
7856                 }
7857         }
7858
7859         /* Map to POSIX errors */
7860         switch (e) {
7861         case EACCES:
7862                 exerrno = 126;
7863                 break;
7864         case ENOENT:
7865                 exerrno = 127;
7866                 break;
7867         default:
7868                 exerrno = 2;
7869                 break;
7870         }
7871         exitstatus = exerrno;
7872         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7873                 prog, e, suppress_int));
7874         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7875         /* NOTREACHED */
7876 }
7877
7878 static void
7879 printentry(struct tblentry *cmdp)
7880 {
7881         int idx;
7882         const char *path;
7883         char *name;
7884
7885         idx = cmdp->param.index;
7886         path = pathval();
7887         do {
7888                 name = path_advance(&path, cmdp->cmdname);
7889                 stunalloc(name);
7890         } while (--idx >= 0);
7891         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7892 }
7893
7894 /*
7895  * Clear out command entries.  The argument specifies the first entry in
7896  * PATH which has changed.
7897  */
7898 static void
7899 clearcmdentry(int firstchange)
7900 {
7901         struct tblentry **tblp;
7902         struct tblentry **pp;
7903         struct tblentry *cmdp;
7904
7905         INT_OFF;
7906         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7907                 pp = tblp;
7908                 while ((cmdp = *pp) != NULL) {
7909                         if ((cmdp->cmdtype == CMDNORMAL &&
7910                              cmdp->param.index >= firstchange)
7911                          || (cmdp->cmdtype == CMDBUILTIN &&
7912                              builtinloc >= firstchange)
7913                         ) {
7914                                 *pp = cmdp->next;
7915                                 free(cmdp);
7916                         } else {
7917                                 pp = &cmdp->next;
7918                         }
7919                 }
7920         }
7921         INT_ON;
7922 }
7923
7924 /*
7925  * Locate a command in the command hash table.  If "add" is nonzero,
7926  * add the command to the table if it is not already present.  The
7927  * variable "lastcmdentry" is set to point to the address of the link
7928  * pointing to the entry, so that delete_cmd_entry can delete the
7929  * entry.
7930  *
7931  * Interrupts must be off if called with add != 0.
7932  */
7933 static struct tblentry **lastcmdentry;
7934
7935 static struct tblentry *
7936 cmdlookup(const char *name, int add)
7937 {
7938         unsigned int hashval;
7939         const char *p;
7940         struct tblentry *cmdp;
7941         struct tblentry **pp;
7942
7943         p = name;
7944         hashval = (unsigned char)*p << 4;
7945         while (*p)
7946                 hashval += (unsigned char)*p++;
7947         hashval &= 0x7FFF;
7948         pp = &cmdtable[hashval % CMDTABLESIZE];
7949         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7950                 if (strcmp(cmdp->cmdname, name) == 0)
7951                         break;
7952                 pp = &cmdp->next;
7953         }
7954         if (add && cmdp == NULL) {
7955                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7956                                 + strlen(name)
7957                                 /* + 1 - already done because
7958                                  * tblentry::cmdname is char[1] */);
7959                 /*cmdp->next = NULL; - ckzalloc did it */
7960                 cmdp->cmdtype = CMDUNKNOWN;
7961                 strcpy(cmdp->cmdname, name);
7962         }
7963         lastcmdentry = pp;
7964         return cmdp;
7965 }
7966
7967 /*
7968  * Delete the command entry returned on the last lookup.
7969  */
7970 static void
7971 delete_cmd_entry(void)
7972 {
7973         struct tblentry *cmdp;
7974
7975         INT_OFF;
7976         cmdp = *lastcmdentry;
7977         *lastcmdentry = cmdp->next;
7978         if (cmdp->cmdtype == CMDFUNCTION)
7979                 freefunc(cmdp->param.func);
7980         free(cmdp);
7981         INT_ON;
7982 }
7983
7984 /*
7985  * Add a new command entry, replacing any existing command entry for
7986  * the same name - except special builtins.
7987  */
7988 static void
7989 addcmdentry(char *name, struct cmdentry *entry)
7990 {
7991         struct tblentry *cmdp;
7992
7993         cmdp = cmdlookup(name, 1);
7994         if (cmdp->cmdtype == CMDFUNCTION) {
7995                 freefunc(cmdp->param.func);
7996         }
7997         cmdp->cmdtype = entry->cmdtype;
7998         cmdp->param = entry->u;
7999         cmdp->rehash = 0;
8000 }
8001
8002 static int FAST_FUNC
8003 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8004 {
8005         struct tblentry **pp;
8006         struct tblentry *cmdp;
8007         int c;
8008         struct cmdentry entry;
8009         char *name;
8010
8011         if (nextopt("r") != '\0') {
8012                 clearcmdentry(0);
8013                 return 0;
8014         }
8015
8016         if (*argptr == NULL) {
8017                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8018                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8019                                 if (cmdp->cmdtype == CMDNORMAL)
8020                                         printentry(cmdp);
8021                         }
8022                 }
8023                 return 0;
8024         }
8025
8026         c = 0;
8027         while ((name = *argptr) != NULL) {
8028                 cmdp = cmdlookup(name, 0);
8029                 if (cmdp != NULL
8030                  && (cmdp->cmdtype == CMDNORMAL
8031                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8032                 ) {
8033                         delete_cmd_entry();
8034                 }
8035                 find_command(name, &entry, DO_ERR, pathval());
8036                 if (entry.cmdtype == CMDUNKNOWN)
8037                         c = 1;
8038                 argptr++;
8039         }
8040         return c;
8041 }
8042
8043 /*
8044  * Called when a cd is done.  Marks all commands so the next time they
8045  * are executed they will be rehashed.
8046  */
8047 static void
8048 hashcd(void)
8049 {
8050         struct tblentry **pp;
8051         struct tblentry *cmdp;
8052
8053         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8054                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8055                         if (cmdp->cmdtype == CMDNORMAL
8056                          || (cmdp->cmdtype == CMDBUILTIN
8057                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8058                              && builtinloc > 0)
8059                         ) {
8060                                 cmdp->rehash = 1;
8061                         }
8062                 }
8063         }
8064 }
8065
8066 /*
8067  * Fix command hash table when PATH changed.
8068  * Called before PATH is changed.  The argument is the new value of PATH;
8069  * pathval() still returns the old value at this point.
8070  * Called with interrupts off.
8071  */
8072 static void FAST_FUNC
8073 changepath(const char *new)
8074 {
8075         const char *old;
8076         int firstchange;
8077         int idx;
8078         int idx_bltin;
8079
8080         old = pathval();
8081         firstchange = 9999;     /* assume no change */
8082         idx = 0;
8083         idx_bltin = -1;
8084         for (;;) {
8085                 if (*old != *new) {
8086                         firstchange = idx;
8087                         if ((*old == '\0' && *new == ':')
8088                          || (*old == ':' && *new == '\0')
8089                         ) {
8090                                 firstchange++;
8091                         }
8092                         old = new;      /* ignore subsequent differences */
8093                 }
8094                 if (*new == '\0')
8095                         break;
8096                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8097                         idx_bltin = idx;
8098                 if (*new == ':')
8099                         idx++;
8100                 new++;
8101                 old++;
8102         }
8103         if (builtinloc < 0 && idx_bltin >= 0)
8104                 builtinloc = idx_bltin;             /* zap builtins */
8105         if (builtinloc >= 0 && idx_bltin < 0)
8106                 firstchange = 0;
8107         clearcmdentry(firstchange);
8108         builtinloc = idx_bltin;
8109 }
8110 enum {
8111         TEOF,
8112         TNL,
8113         TREDIR,
8114         TWORD,
8115         TSEMI,
8116         TBACKGND,
8117         TAND,
8118         TOR,
8119         TPIPE,
8120         TLP,
8121         TRP,
8122         TENDCASE,
8123         TENDBQUOTE,
8124         TNOT,
8125         TCASE,
8126         TDO,
8127         TDONE,
8128         TELIF,
8129         TELSE,
8130         TESAC,
8131         TFI,
8132         TFOR,
8133 #if BASH_FUNCTION
8134         TFUNCTION,
8135 #endif
8136         TIF,
8137         TIN,
8138         TTHEN,
8139         TUNTIL,
8140         TWHILE,
8141         TBEGIN,
8142         TEND
8143 };
8144 typedef smallint token_id_t;
8145
8146 /* Nth bit indicates if token marks the end of a list */
8147 enum {
8148         tokendlist = 0
8149         /*  0 */ | (1u << TEOF)
8150         /*  1 */ | (0u << TNL)
8151         /*  2 */ | (0u << TREDIR)
8152         /*  3 */ | (0u << TWORD)
8153         /*  4 */ | (0u << TSEMI)
8154         /*  5 */ | (0u << TBACKGND)
8155         /*  6 */ | (0u << TAND)
8156         /*  7 */ | (0u << TOR)
8157         /*  8 */ | (0u << TPIPE)
8158         /*  9 */ | (0u << TLP)
8159         /* 10 */ | (1u << TRP)
8160         /* 11 */ | (1u << TENDCASE)
8161         /* 12 */ | (1u << TENDBQUOTE)
8162         /* 13 */ | (0u << TNOT)
8163         /* 14 */ | (0u << TCASE)
8164         /* 15 */ | (1u << TDO)
8165         /* 16 */ | (1u << TDONE)
8166         /* 17 */ | (1u << TELIF)
8167         /* 18 */ | (1u << TELSE)
8168         /* 19 */ | (1u << TESAC)
8169         /* 20 */ | (1u << TFI)
8170         /* 21 */ | (0u << TFOR)
8171 #if BASH_FUNCTION
8172         /* 22 */ | (0u << TFUNCTION)
8173 #endif
8174         /* 23 */ | (0u << TIF)
8175         /* 24 */ | (0u << TIN)
8176         /* 25 */ | (1u << TTHEN)
8177         /* 26 */ | (0u << TUNTIL)
8178         /* 27 */ | (0u << TWHILE)
8179         /* 28 */ | (0u << TBEGIN)
8180         /* 29 */ | (1u << TEND)
8181         , /* thus far 29 bits used */
8182 };
8183
8184 static const char *const tokname_array[] = {
8185         "end of file",
8186         "newline",
8187         "redirection",
8188         "word",
8189         ";",
8190         "&",
8191         "&&",
8192         "||",
8193         "|",
8194         "(",
8195         ")",
8196         ";;",
8197         "`",
8198 #define KWDOFFSET 13
8199         /* the following are keywords */
8200         "!",
8201         "case",
8202         "do",
8203         "done",
8204         "elif",
8205         "else",
8206         "esac",
8207         "fi",
8208         "for",
8209 #if BASH_FUNCTION
8210         "function",
8211 #endif
8212         "if",
8213         "in",
8214         "then",
8215         "until",
8216         "while",
8217         "{",
8218         "}",
8219 };
8220
8221 /* Wrapper around strcmp for qsort/bsearch/... */
8222 static int
8223 pstrcmp(const void *a, const void *b)
8224 {
8225         return strcmp((char*)a, *(char**)b);
8226 }
8227
8228 static const char *const *
8229 findkwd(const char *s)
8230 {
8231         return bsearch(s, tokname_array + KWDOFFSET,
8232                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8233                         sizeof(tokname_array[0]), pstrcmp);
8234 }
8235
8236 /*
8237  * Locate and print what a word is...
8238  */
8239 static int
8240 describe_command(char *command, const char *path, int describe_command_verbose)
8241 {
8242         struct cmdentry entry;
8243 #if ENABLE_ASH_ALIAS
8244         const struct alias *ap;
8245 #endif
8246
8247         path = path ? path : pathval();
8248
8249         if (describe_command_verbose) {
8250                 out1str(command);
8251         }
8252
8253         /* First look at the keywords */
8254         if (findkwd(command)) {
8255                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8256                 goto out;
8257         }
8258
8259 #if ENABLE_ASH_ALIAS
8260         /* Then look at the aliases */
8261         ap = lookupalias(command, 0);
8262         if (ap != NULL) {
8263                 if (!describe_command_verbose) {
8264                         out1str("alias ");
8265                         printalias(ap);
8266                         return 0;
8267                 }
8268                 out1fmt(" is an alias for %s", ap->val);
8269                 goto out;
8270         }
8271 #endif
8272         /* Brute force */
8273         find_command(command, &entry, DO_ABS, path);
8274
8275         switch (entry.cmdtype) {
8276         case CMDNORMAL: {
8277                 int j = entry.u.index;
8278                 char *p;
8279                 if (j < 0) {
8280                         p = command;
8281                 } else {
8282                         do {
8283                                 p = path_advance(&path, command);
8284                                 stunalloc(p);
8285                         } while (--j >= 0);
8286                 }
8287                 if (describe_command_verbose) {
8288                         out1fmt(" is %s", p);
8289                 } else {
8290                         out1str(p);
8291                 }
8292                 break;
8293         }
8294
8295         case CMDFUNCTION:
8296                 if (describe_command_verbose) {
8297                         out1str(" is a shell function");
8298                 } else {
8299                         out1str(command);
8300                 }
8301                 break;
8302
8303         case CMDBUILTIN:
8304                 if (describe_command_verbose) {
8305                         out1fmt(" is a %sshell builtin",
8306                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8307                                         "special " : nullstr
8308                         );
8309                 } else {
8310                         out1str(command);
8311                 }
8312                 break;
8313
8314         default:
8315                 if (describe_command_verbose) {
8316                         out1str(": not found\n");
8317                 }
8318                 return 127;
8319         }
8320  out:
8321         out1str("\n");
8322         return 0;
8323 }
8324
8325 static int FAST_FUNC
8326 typecmd(int argc UNUSED_PARAM, char **argv)
8327 {
8328         int i = 1;
8329         int err = 0;
8330         int verbose = 1;
8331
8332         /* type -p ... ? (we don't bother checking for 'p') */
8333         if (argv[1] && argv[1][0] == '-') {
8334                 i++;
8335                 verbose = 0;
8336         }
8337         while (argv[i]) {
8338                 err |= describe_command(argv[i++], NULL, verbose);
8339         }
8340         return err;
8341 }
8342
8343 #if ENABLE_ASH_CMDCMD
8344 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8345 static char **
8346 parse_command_args(char **argv, const char **path)
8347 {
8348         char *cp, c;
8349
8350         for (;;) {
8351                 cp = *++argv;
8352                 if (!cp)
8353                         return NULL;
8354                 if (*cp++ != '-')
8355                         break;
8356                 c = *cp++;
8357                 if (!c)
8358                         break;
8359                 if (c == '-' && !*cp) {
8360                         if (!*++argv)
8361                                 return NULL;
8362                         break;
8363                 }
8364                 do {
8365                         switch (c) {
8366                         case 'p':
8367                                 *path = bb_default_path;
8368                                 break;
8369                         default:
8370                                 /* run 'typecmd' for other options */
8371                                 return NULL;
8372                         }
8373                         c = *cp++;
8374                 } while (c);
8375         }
8376         return argv;
8377 }
8378
8379 static int FAST_FUNC
8380 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8381 {
8382         char *cmd;
8383         int c;
8384         enum {
8385                 VERIFY_BRIEF = 1,
8386                 VERIFY_VERBOSE = 2,
8387         } verify = 0;
8388         const char *path = NULL;
8389
8390         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8391          * never reaches this function.
8392          */
8393
8394         while ((c = nextopt("pvV")) != '\0')
8395                 if (c == 'V')
8396                         verify |= VERIFY_VERBOSE;
8397                 else if (c == 'v')
8398                         /*verify |= VERIFY_BRIEF*/;
8399 #if DEBUG
8400                 else if (c != 'p')
8401                         abort();
8402 #endif
8403                 else
8404                         path = bb_default_path;
8405
8406         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8407         cmd = *argptr;
8408         if (/*verify && */ cmd)
8409                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8410
8411         return 0;
8412 }
8413 #endif
8414
8415
8416 /*static int funcblocksize;     // size of structures in function */
8417 /*static int funcstringsize;    // size of strings in node */
8418 static void *funcblock;         /* block to allocate function from */
8419 static char *funcstring_end;    /* end of block to allocate strings from */
8420
8421 /* flags in argument to evaltree */
8422 #define EV_EXIT    01           /* exit after evaluating tree */
8423 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8424
8425 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8426         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8427         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8428         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8429         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8430         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8431         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8432         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8433         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8434         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8435         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8436         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8437         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8438         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8439         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8440         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8441         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8442         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8443 #if BASH_REDIR_OUTPUT
8444         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8445 #endif
8446         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8447         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8448         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8449         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8450         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8451         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8452         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8453         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8454         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8455 };
8456
8457 static int calcsize(int funcblocksize, union node *n);
8458
8459 static int
8460 sizenodelist(int funcblocksize, struct nodelist *lp)
8461 {
8462         while (lp) {
8463                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8464                 funcblocksize = calcsize(funcblocksize, lp->n);
8465                 lp = lp->next;
8466         }
8467         return funcblocksize;
8468 }
8469
8470 static int
8471 calcsize(int funcblocksize, union node *n)
8472 {
8473         if (n == NULL)
8474                 return funcblocksize;
8475         funcblocksize += nodesize[n->type];
8476         switch (n->type) {
8477         case NCMD:
8478                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8479                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8480                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8481                 break;
8482         case NPIPE:
8483                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8484                 break;
8485         case NREDIR:
8486         case NBACKGND:
8487         case NSUBSHELL:
8488                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8489                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8490                 break;
8491         case NAND:
8492         case NOR:
8493         case NSEMI:
8494         case NWHILE:
8495         case NUNTIL:
8496                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8497                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8498                 break;
8499         case NIF:
8500                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8501                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8502                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8503                 break;
8504         case NFOR:
8505                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8506                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8507                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8508                 break;
8509         case NCASE:
8510                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8511                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8512                 break;
8513         case NCLIST:
8514                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8515                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8516                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8517                 break;
8518         case NDEFUN:
8519         case NARG:
8520                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8521                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8522                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8523                 break;
8524         case NTO:
8525 #if BASH_REDIR_OUTPUT
8526         case NTO2:
8527 #endif
8528         case NCLOBBER:
8529         case NFROM:
8530         case NFROMTO:
8531         case NAPPEND:
8532                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8533                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8534                 break;
8535         case NTOFD:
8536         case NFROMFD:
8537                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8538                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8539         break;
8540         case NHERE:
8541         case NXHERE:
8542                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8543                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8544                 break;
8545         case NNOT:
8546                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8547                 break;
8548         };
8549         return funcblocksize;
8550 }
8551
8552 static char *
8553 nodeckstrdup(char *s)
8554 {
8555         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8556         return strcpy(funcstring_end, s);
8557 }
8558
8559 static union node *copynode(union node *);
8560
8561 static struct nodelist *
8562 copynodelist(struct nodelist *lp)
8563 {
8564         struct nodelist *start;
8565         struct nodelist **lpp;
8566
8567         lpp = &start;
8568         while (lp) {
8569                 *lpp = funcblock;
8570                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8571                 (*lpp)->n = copynode(lp->n);
8572                 lp = lp->next;
8573                 lpp = &(*lpp)->next;
8574         }
8575         *lpp = NULL;
8576         return start;
8577 }
8578
8579 static union node *
8580 copynode(union node *n)
8581 {
8582         union node *new;
8583
8584         if (n == NULL)
8585                 return NULL;
8586         new = funcblock;
8587         funcblock = (char *) funcblock + nodesize[n->type];
8588
8589         switch (n->type) {
8590         case NCMD:
8591                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8592                 new->ncmd.args = copynode(n->ncmd.args);
8593                 new->ncmd.assign = copynode(n->ncmd.assign);
8594                 break;
8595         case NPIPE:
8596                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8597                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8598                 break;
8599         case NREDIR:
8600         case NBACKGND:
8601         case NSUBSHELL:
8602                 new->nredir.redirect = copynode(n->nredir.redirect);
8603                 new->nredir.n = copynode(n->nredir.n);
8604                 break;
8605         case NAND:
8606         case NOR:
8607         case NSEMI:
8608         case NWHILE:
8609         case NUNTIL:
8610                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8611                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8612                 break;
8613         case NIF:
8614                 new->nif.elsepart = copynode(n->nif.elsepart);
8615                 new->nif.ifpart = copynode(n->nif.ifpart);
8616                 new->nif.test = copynode(n->nif.test);
8617                 break;
8618         case NFOR:
8619                 new->nfor.var = nodeckstrdup(n->nfor.var);
8620                 new->nfor.body = copynode(n->nfor.body);
8621                 new->nfor.args = copynode(n->nfor.args);
8622                 break;
8623         case NCASE:
8624                 new->ncase.cases = copynode(n->ncase.cases);
8625                 new->ncase.expr = copynode(n->ncase.expr);
8626                 break;
8627         case NCLIST:
8628                 new->nclist.body = copynode(n->nclist.body);
8629                 new->nclist.pattern = copynode(n->nclist.pattern);
8630                 new->nclist.next = copynode(n->nclist.next);
8631                 break;
8632         case NDEFUN:
8633         case NARG:
8634                 new->narg.backquote = copynodelist(n->narg.backquote);
8635                 new->narg.text = nodeckstrdup(n->narg.text);
8636                 new->narg.next = copynode(n->narg.next);
8637                 break;
8638         case NTO:
8639 #if BASH_REDIR_OUTPUT
8640         case NTO2:
8641 #endif
8642         case NCLOBBER:
8643         case NFROM:
8644         case NFROMTO:
8645         case NAPPEND:
8646                 new->nfile.fname = copynode(n->nfile.fname);
8647                 new->nfile.fd = n->nfile.fd;
8648                 new->nfile.next = copynode(n->nfile.next);
8649                 break;
8650         case NTOFD:
8651         case NFROMFD:
8652                 new->ndup.vname = copynode(n->ndup.vname);
8653                 new->ndup.dupfd = n->ndup.dupfd;
8654                 new->ndup.fd = n->ndup.fd;
8655                 new->ndup.next = copynode(n->ndup.next);
8656                 break;
8657         case NHERE:
8658         case NXHERE:
8659                 new->nhere.doc = copynode(n->nhere.doc);
8660                 new->nhere.fd = n->nhere.fd;
8661                 new->nhere.next = copynode(n->nhere.next);
8662                 break;
8663         case NNOT:
8664                 new->nnot.com = copynode(n->nnot.com);
8665                 break;
8666         };
8667         new->type = n->type;
8668         return new;
8669 }
8670
8671 /*
8672  * Make a copy of a parse tree.
8673  */
8674 static struct funcnode *
8675 copyfunc(union node *n)
8676 {
8677         struct funcnode *f;
8678         size_t blocksize;
8679
8680         /*funcstringsize = 0;*/
8681         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8682         f = ckzalloc(blocksize /* + funcstringsize */);
8683         funcblock = (char *) f + offsetof(struct funcnode, n);
8684         funcstring_end = (char *) f + blocksize;
8685         copynode(n);
8686         /* f->count = 0; - ckzalloc did it */
8687         return f;
8688 }
8689
8690 /*
8691  * Define a shell function.
8692  */
8693 static void
8694 defun(union node *func)
8695 {
8696         struct cmdentry entry;
8697
8698         INT_OFF;
8699         entry.cmdtype = CMDFUNCTION;
8700         entry.u.func = copyfunc(func);
8701         addcmdentry(func->narg.text, &entry);
8702         INT_ON;
8703 }
8704
8705 /* Reasons for skipping commands (see comment on breakcmd routine) */
8706 #define SKIPBREAK      (1 << 0)
8707 #define SKIPCONT       (1 << 1)
8708 #define SKIPFUNC       (1 << 2)
8709 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8710 static int skipcount;           /* number of levels to skip */
8711 static int funcnest;            /* depth of function calls */
8712 static int loopnest;            /* current loop nesting level */
8713
8714 /* Forward decl way out to parsing code - dotrap needs it */
8715 static int evalstring(char *s, int flags);
8716
8717 /* Called to execute a trap.
8718  * Single callsite - at the end of evaltree().
8719  * If we return non-zero, evaltree raises EXEXIT exception.
8720  *
8721  * Perhaps we should avoid entering new trap handlers
8722  * while we are executing a trap handler. [is it a TODO?]
8723  */
8724 static void
8725 dotrap(void)
8726 {
8727         uint8_t *g;
8728         int sig;
8729         uint8_t last_status;
8730
8731         if (!pending_sig)
8732                 return;
8733
8734         last_status = exitstatus;
8735         pending_sig = 0;
8736         barrier();
8737
8738         TRACE(("dotrap entered\n"));
8739         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8740                 char *p;
8741
8742                 if (!*g)
8743                         continue;
8744
8745                 if (evalskip) {
8746                         pending_sig = sig;
8747                         break;
8748                 }
8749
8750                 p = trap[sig];
8751                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8752                  * don't upset it by resetting gotsig[SIGINT-1] */
8753                 if (sig == SIGINT && !p)
8754                         continue;
8755
8756                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8757                 *g = 0;
8758                 if (!p)
8759                         continue;
8760                 evalstring(p, 0);
8761         }
8762         exitstatus = last_status;
8763         TRACE(("dotrap returns\n"));
8764 }
8765
8766 /* forward declarations - evaluation is fairly recursive business... */
8767 static int evalloop(union node *, int);
8768 static int evalfor(union node *, int);
8769 static int evalcase(union node *, int);
8770 static int evalsubshell(union node *, int);
8771 static void expredir(union node *);
8772 static int evalpipe(union node *, int);
8773 static int evalcommand(union node *, int);
8774 static int evalbltin(const struct builtincmd *, int, char **, int);
8775 static void prehash(union node *);
8776
8777 /*
8778  * Evaluate a parse tree.  The value is left in the global variable
8779  * exitstatus.
8780  */
8781 static int
8782 evaltree(union node *n, int flags)
8783 {
8784         int checkexit = 0;
8785         int (*evalfn)(union node *, int);
8786         int status = 0;
8787
8788         if (n == NULL) {
8789                 TRACE(("evaltree(NULL) called\n"));
8790                 goto out;
8791         }
8792         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8793
8794         dotrap();
8795
8796         switch (n->type) {
8797         default:
8798 #if DEBUG
8799                 out1fmt("Node type = %d\n", n->type);
8800                 fflush_all();
8801                 break;
8802 #endif
8803         case NNOT:
8804                 status = !evaltree(n->nnot.com, EV_TESTED);
8805                 goto setstatus;
8806         case NREDIR:
8807                 expredir(n->nredir.redirect);
8808                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8809                 if (!status) {
8810                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8811                 }
8812                 if (n->nredir.redirect)
8813                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8814                 goto setstatus;
8815         case NCMD:
8816                 evalfn = evalcommand;
8817  checkexit:
8818                 if (eflag && !(flags & EV_TESTED))
8819                         checkexit = ~0;
8820                 goto calleval;
8821         case NFOR:
8822                 evalfn = evalfor;
8823                 goto calleval;
8824         case NWHILE:
8825         case NUNTIL:
8826                 evalfn = evalloop;
8827                 goto calleval;
8828         case NSUBSHELL:
8829         case NBACKGND:
8830                 evalfn = evalsubshell;
8831                 goto checkexit;
8832         case NPIPE:
8833                 evalfn = evalpipe;
8834                 goto checkexit;
8835         case NCASE:
8836                 evalfn = evalcase;
8837                 goto calleval;
8838         case NAND:
8839         case NOR:
8840         case NSEMI: {
8841
8842 #if NAND + 1 != NOR
8843 #error NAND + 1 != NOR
8844 #endif
8845 #if NOR + 1 != NSEMI
8846 #error NOR + 1 != NSEMI
8847 #endif
8848                 unsigned is_or = n->type - NAND;
8849                 status = evaltree(
8850                         n->nbinary.ch1,
8851                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8852                 );
8853                 if ((!status) == is_or || evalskip)
8854                         break;
8855                 n = n->nbinary.ch2;
8856  evaln:
8857                 evalfn = evaltree;
8858  calleval:
8859                 status = evalfn(n, flags);
8860                 goto setstatus;
8861         }
8862         case NIF:
8863                 status = evaltree(n->nif.test, EV_TESTED);
8864                 if (evalskip)
8865                         break;
8866                 if (!status) {
8867                         n = n->nif.ifpart;
8868                         goto evaln;
8869                 }
8870                 if (n->nif.elsepart) {
8871                         n = n->nif.elsepart;
8872                         goto evaln;
8873                 }
8874                 status = 0;
8875                 goto setstatus;
8876         case NDEFUN:
8877                 defun(n);
8878                 /* Not necessary. To test it:
8879                  * "false; f() { qwerty; }; echo $?" should print 0.
8880                  */
8881                 /* status = 0; */
8882  setstatus:
8883                 exitstatus = status;
8884                 break;
8885         }
8886  out:
8887         /* Order of checks below is important:
8888          * signal handlers trigger before exit caused by "set -e".
8889          */
8890         dotrap();
8891
8892         if (checkexit & status)
8893                 raise_exception(EXEXIT);
8894         if (flags & EV_EXIT)
8895                 raise_exception(EXEXIT);
8896
8897         TRACE(("leaving evaltree (no interrupts)\n"));
8898         return exitstatus;
8899 }
8900
8901 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8902 static
8903 #endif
8904 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8905
8906 static int
8907 skiploop(void)
8908 {
8909         int skip = evalskip;
8910
8911         switch (skip) {
8912         case 0:
8913                 break;
8914         case SKIPBREAK:
8915         case SKIPCONT:
8916                 if (--skipcount <= 0) {
8917                         evalskip = 0;
8918                         break;
8919                 }
8920                 skip = SKIPBREAK;
8921                 break;
8922         }
8923         return skip;
8924 }
8925
8926 static int
8927 evalloop(union node *n, int flags)
8928 {
8929         int skip;
8930         int status;
8931
8932         loopnest++;
8933         status = 0;
8934         flags &= EV_TESTED;
8935         do {
8936                 int i;
8937
8938                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8939                 skip = skiploop();
8940                 if (skip == SKIPFUNC)
8941                         status = i;
8942                 if (skip)
8943                         continue;
8944                 if (n->type != NWHILE)
8945                         i = !i;
8946                 if (i != 0)
8947                         break;
8948                 status = evaltree(n->nbinary.ch2, flags);
8949                 skip = skiploop();
8950         } while (!(skip & ~SKIPCONT));
8951         loopnest--;
8952
8953         return status;
8954 }
8955
8956 static int
8957 evalfor(union node *n, int flags)
8958 {
8959         struct arglist arglist;
8960         union node *argp;
8961         struct strlist *sp;
8962         struct stackmark smark;
8963         int status = 0;
8964
8965         setstackmark(&smark);
8966         arglist.list = NULL;
8967         arglist.lastp = &arglist.list;
8968         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8969                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8970         }
8971         *arglist.lastp = NULL;
8972
8973         loopnest++;
8974         flags &= EV_TESTED;
8975         for (sp = arglist.list; sp; sp = sp->next) {
8976                 setvar0(n->nfor.var, sp->text);
8977                 status = evaltree(n->nfor.body, flags);
8978                 if (skiploop() & ~SKIPCONT)
8979                         break;
8980         }
8981         loopnest--;
8982         popstackmark(&smark);
8983
8984         return status;
8985 }
8986
8987 static int
8988 evalcase(union node *n, int flags)
8989 {
8990         union node *cp;
8991         union node *patp;
8992         struct arglist arglist;
8993         struct stackmark smark;
8994         int status = 0;
8995
8996         setstackmark(&smark);
8997         arglist.list = NULL;
8998         arglist.lastp = &arglist.list;
8999         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9000         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9001                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9002                         if (casematch(patp, arglist.list->text)) {
9003                                 /* Ensure body is non-empty as otherwise
9004                                  * EV_EXIT may prevent us from setting the
9005                                  * exit status.
9006                                  */
9007                                 if (evalskip == 0 && cp->nclist.body) {
9008                                         status = evaltree(cp->nclist.body, flags);
9009                                 }
9010                                 goto out;
9011                         }
9012                 }
9013         }
9014  out:
9015         popstackmark(&smark);
9016
9017         return status;
9018 }
9019
9020 /*
9021  * Kick off a subshell to evaluate a tree.
9022  */
9023 static int
9024 evalsubshell(union node *n, int flags)
9025 {
9026         struct job *jp;
9027         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9028         int status;
9029
9030         expredir(n->nredir.redirect);
9031         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9032                 goto nofork;
9033         INT_OFF;
9034         if (backgnd == FORK_FG)
9035                 get_tty_state();
9036         jp = makejob(/*n,*/ 1);
9037         if (forkshell(jp, n, backgnd) == 0) {
9038                 /* child */
9039                 INT_ON;
9040                 flags |= EV_EXIT;
9041                 if (backgnd)
9042                         flags &= ~EV_TESTED;
9043  nofork:
9044                 redirect(n->nredir.redirect, 0);
9045                 evaltreenr(n->nredir.n, flags);
9046                 /* never returns */
9047         }
9048         /* parent */
9049         status = 0;
9050         if (backgnd == FORK_FG)
9051                 status = waitforjob(jp);
9052         INT_ON;
9053         return status;
9054 }
9055
9056 /*
9057  * Compute the names of the files in a redirection list.
9058  */
9059 static void fixredir(union node *, const char *, int);
9060 static void
9061 expredir(union node *n)
9062 {
9063         union node *redir;
9064
9065         for (redir = n; redir; redir = redir->nfile.next) {
9066                 struct arglist fn;
9067
9068                 fn.list = NULL;
9069                 fn.lastp = &fn.list;
9070                 switch (redir->type) {
9071                 case NFROMTO:
9072                 case NFROM:
9073                 case NTO:
9074 #if BASH_REDIR_OUTPUT
9075                 case NTO2:
9076 #endif
9077                 case NCLOBBER:
9078                 case NAPPEND:
9079                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9080                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9081 #if BASH_REDIR_OUTPUT
9082  store_expfname:
9083 #endif
9084 #if 0
9085 // By the design of stack allocator, the loop of this kind:
9086 //      while true; do while true; do break; done </dev/null; done
9087 // will look like a memory leak: ash plans to free expfname's
9088 // of "/dev/null" as soon as it finishes running the loop
9089 // (in this case, never).
9090 // This "fix" is wrong:
9091                         if (redir->nfile.expfname)
9092                                 stunalloc(redir->nfile.expfname);
9093 // It results in corrupted state of stacked allocations.
9094 #endif
9095                         redir->nfile.expfname = fn.list->text;
9096                         break;
9097                 case NFROMFD:
9098                 case NTOFD: /* >& */
9099                         if (redir->ndup.vname) {
9100                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9101                                 if (fn.list == NULL)
9102                                         ash_msg_and_raise_error("redir error");
9103 #if BASH_REDIR_OUTPUT
9104 //FIXME: we used expandarg with different args!
9105                                 if (!isdigit_str9(fn.list->text)) {
9106                                         /* >&file, not >&fd */
9107                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9108                                                 ash_msg_and_raise_error("redir error");
9109                                         redir->type = NTO2;
9110                                         goto store_expfname;
9111                                 }
9112 #endif
9113                                 fixredir(redir, fn.list->text, 1);
9114                         }
9115                         break;
9116                 }
9117         }
9118 }
9119
9120 /*
9121  * Evaluate a pipeline.  All the processes in the pipeline are children
9122  * of the process creating the pipeline.  (This differs from some versions
9123  * of the shell, which make the last process in a pipeline the parent
9124  * of all the rest.)
9125  */
9126 static int
9127 evalpipe(union node *n, int flags)
9128 {
9129         struct job *jp;
9130         struct nodelist *lp;
9131         int pipelen;
9132         int prevfd;
9133         int pip[2];
9134         int status = 0;
9135
9136         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9137         pipelen = 0;
9138         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9139                 pipelen++;
9140         flags |= EV_EXIT;
9141         INT_OFF;
9142         if (n->npipe.pipe_backgnd == 0)
9143                 get_tty_state();
9144         jp = makejob(/*n,*/ pipelen);
9145         prevfd = -1;
9146         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9147                 prehash(lp->n);
9148                 pip[1] = -1;
9149                 if (lp->next) {
9150                         if (pipe(pip) < 0) {
9151                                 close(prevfd);
9152                                 ash_msg_and_raise_error("pipe call failed");
9153                         }
9154                 }
9155                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9156                         /* child */
9157                         INT_ON;
9158                         if (pip[1] >= 0) {
9159                                 close(pip[0]);
9160                         }
9161                         if (prevfd > 0) {
9162                                 dup2(prevfd, 0);
9163                                 close(prevfd);
9164                         }
9165                         if (pip[1] > 1) {
9166                                 dup2(pip[1], 1);
9167                                 close(pip[1]);
9168                         }
9169                         evaltreenr(lp->n, flags);
9170                         /* never returns */
9171                 }
9172                 /* parent */
9173                 if (prevfd >= 0)
9174                         close(prevfd);
9175                 prevfd = pip[0];
9176                 /* Don't want to trigger debugging */
9177                 if (pip[1] != -1)
9178                         close(pip[1]);
9179         }
9180         if (n->npipe.pipe_backgnd == 0) {
9181                 status = waitforjob(jp);
9182                 TRACE(("evalpipe:  job done exit status %d\n", status));
9183         }
9184         INT_ON;
9185
9186         return status;
9187 }
9188
9189 /*
9190  * Controls whether the shell is interactive or not.
9191  */
9192 static void
9193 setinteractive(int on)
9194 {
9195         static smallint is_interactive;
9196
9197         if (++on == is_interactive)
9198                 return;
9199         is_interactive = on;
9200         setsignal(SIGINT);
9201         setsignal(SIGQUIT);
9202         setsignal(SIGTERM);
9203 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9204         if (is_interactive > 1) {
9205                 /* Looks like they want an interactive shell */
9206                 static smallint did_banner;
9207
9208                 if (!did_banner) {
9209                         /* note: ash and hush share this string */
9210                         out1fmt("\n\n%s %s\n"
9211                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9212                                 "\n",
9213                                 bb_banner,
9214                                 "built-in shell (ash)"
9215                         );
9216                         did_banner = 1;
9217                 }
9218         }
9219 #endif
9220 }
9221
9222 static void
9223 optschanged(void)
9224 {
9225 #if DEBUG
9226         opentrace();
9227 #endif
9228         setinteractive(iflag);
9229         setjobctl(mflag);
9230 #if ENABLE_FEATURE_EDITING_VI
9231         if (viflag)
9232                 line_input_state->flags |= VI_MODE;
9233         else
9234                 line_input_state->flags &= ~VI_MODE;
9235 #else
9236         viflag = 0; /* forcibly keep the option off */
9237 #endif
9238 }
9239
9240 static struct localvar *localvars;
9241
9242 /*
9243  * Called after a function returns.
9244  * Interrupts must be off.
9245  */
9246 static void
9247 poplocalvars(void)
9248 {
9249         struct localvar *lvp;
9250         struct var *vp;
9251
9252         while ((lvp = localvars) != NULL) {
9253                 localvars = lvp->next;
9254                 vp = lvp->vp;
9255                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9256                 if (vp == NULL) {       /* $- saved */
9257                         memcpy(optlist, lvp->text, sizeof(optlist));
9258                         free((char*)lvp->text);
9259                         optschanged();
9260                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9261                         unsetvar(vp->var_text);
9262                 } else {
9263                         if (vp->var_func)
9264                                 vp->var_func(var_end(lvp->text));
9265                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9266                                 free((char*)vp->var_text);
9267                         vp->flags = lvp->flags;
9268                         vp->var_text = lvp->text;
9269                 }
9270                 free(lvp);
9271         }
9272 }
9273
9274 static int
9275 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9276 {
9277         volatile struct shparam saveparam;
9278         struct localvar *volatile savelocalvars;
9279         struct jmploc *volatile savehandler;
9280         struct jmploc jmploc;
9281         int e;
9282
9283         saveparam = shellparam;
9284         savelocalvars = localvars;
9285         savehandler = exception_handler;
9286         e = setjmp(jmploc.loc);
9287         if (e) {
9288                 goto funcdone;
9289         }
9290         INT_OFF;
9291         exception_handler = &jmploc;
9292         localvars = NULL;
9293         shellparam.malloced = 0;
9294         func->count++;
9295         funcnest++;
9296         INT_ON;
9297         shellparam.nparam = argc - 1;
9298         shellparam.p = argv + 1;
9299 #if ENABLE_ASH_GETOPTS
9300         shellparam.optind = 1;
9301         shellparam.optoff = -1;
9302 #endif
9303         evaltree(func->n.narg.next, flags & EV_TESTED);
9304  funcdone:
9305         INT_OFF;
9306         funcnest--;
9307         freefunc(func);
9308         poplocalvars();
9309         localvars = savelocalvars;
9310         freeparam(&shellparam);
9311         shellparam = saveparam;
9312         exception_handler = savehandler;
9313         INT_ON;
9314         evalskip &= ~SKIPFUNC;
9315         return e;
9316 }
9317
9318 /*
9319  * Make a variable a local variable.  When a variable is made local, it's
9320  * value and flags are saved in a localvar structure.  The saved values
9321  * will be restored when the shell function returns.  We handle the name
9322  * "-" as a special case: it makes changes to "set +-options" local
9323  * (options will be restored on return from the function).
9324  */
9325 static void
9326 mklocal(char *name)
9327 {
9328         struct localvar *lvp;
9329         struct var **vpp;
9330         struct var *vp;
9331         char *eq = strchr(name, '=');
9332
9333         INT_OFF;
9334         /* Cater for duplicate "local". Examples:
9335          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9336          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9337          */
9338         lvp = localvars;
9339         while (lvp) {
9340                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9341                         if (eq)
9342                                 setvareq(name, 0);
9343                         /* else:
9344                          * it's a duplicate "local VAR" declaration, do nothing
9345                          */
9346                         goto ret;
9347                 }
9348                 lvp = lvp->next;
9349         }
9350
9351         lvp = ckzalloc(sizeof(*lvp));
9352         if (LONE_DASH(name)) {
9353                 char *p;
9354                 p = ckmalloc(sizeof(optlist));
9355                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9356                 vp = NULL;
9357         } else {
9358                 vpp = hashvar(name);
9359                 vp = *findvar(vpp, name);
9360                 if (vp == NULL) {
9361                         /* variable did not exist yet */
9362                         if (eq)
9363                                 setvareq(name, VSTRFIXED);
9364                         else
9365                                 setvar(name, NULL, VSTRFIXED);
9366                         vp = *vpp;      /* the new variable */
9367                         lvp->flags = VUNSET;
9368                 } else {
9369                         lvp->text = vp->var_text;
9370                         lvp->flags = vp->flags;
9371                         /* make sure neither "struct var" nor string gets freed
9372                          * during (un)setting:
9373                          */
9374                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9375                         if (eq)
9376                                 setvareq(name, 0);
9377                         else
9378                                 /* "local VAR" unsets VAR: */
9379                                 setvar0(name, NULL);
9380                 }
9381         }
9382         lvp->vp = vp;
9383         lvp->next = localvars;
9384         localvars = lvp;
9385  ret:
9386         INT_ON;
9387 }
9388
9389 /*
9390  * The "local" command.
9391  */
9392 static int FAST_FUNC
9393 localcmd(int argc UNUSED_PARAM, char **argv)
9394 {
9395         char *name;
9396
9397         if (!funcnest)
9398                 ash_msg_and_raise_error("not in a function");
9399
9400         argv = argptr;
9401         while ((name = *argv++) != NULL) {
9402                 mklocal(name);
9403         }
9404         return 0;
9405 }
9406
9407 static int FAST_FUNC
9408 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9409 {
9410         return 1;
9411 }
9412
9413 static int FAST_FUNC
9414 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9415 {
9416         return 0;
9417 }
9418
9419 static int FAST_FUNC
9420 execcmd(int argc UNUSED_PARAM, char **argv)
9421 {
9422         optionarg = NULL;
9423         while (nextopt("a:") != '\0')
9424                 /* nextopt() sets optionarg to "-a ARGV0" */;
9425
9426         argv = argptr;
9427         if (argv[0]) {
9428                 char *prog;
9429
9430                 iflag = 0;              /* exit on error */
9431                 mflag = 0;
9432                 optschanged();
9433                 /* We should set up signals for "exec CMD"
9434                  * the same way as for "CMD" without "exec".
9435                  * But optschanged->setinteractive->setsignal
9436                  * still thought we are a root shell. Therefore, for example,
9437                  * SIGQUIT is still set to IGN. Fix it:
9438                  */
9439                 shlvl++;
9440                 setsignal(SIGQUIT);
9441                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9442                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9443                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9444
9445                 prog = argv[0];
9446                 if (optionarg)
9447                         argv[0] = optionarg;
9448                 shellexec(prog, argv, pathval(), 0);
9449                 /* NOTREACHED */
9450         }
9451         return 0;
9452 }
9453
9454 /*
9455  * The return command.
9456  */
9457 static int FAST_FUNC
9458 returncmd(int argc UNUSED_PARAM, char **argv)
9459 {
9460         /*
9461          * If called outside a function, do what ksh does;
9462          * skip the rest of the file.
9463          */
9464         evalskip = SKIPFUNC;
9465         return argv[1] ? number(argv[1]) : exitstatus;
9466 }
9467
9468 /* Forward declarations for builtintab[] */
9469 static int breakcmd(int, char **) FAST_FUNC;
9470 static int dotcmd(int, char **) FAST_FUNC;
9471 static int evalcmd(int, char **, int) FAST_FUNC;
9472 static int exitcmd(int, char **) FAST_FUNC;
9473 static int exportcmd(int, char **) FAST_FUNC;
9474 #if ENABLE_ASH_GETOPTS
9475 static int getoptscmd(int, char **) FAST_FUNC;
9476 #endif
9477 #if ENABLE_ASH_HELP
9478 static int helpcmd(int, char **) FAST_FUNC;
9479 #endif
9480 #if MAX_HISTORY
9481 static int historycmd(int, char **) FAST_FUNC;
9482 #endif
9483 #if ENABLE_FEATURE_SH_MATH
9484 static int letcmd(int, char **) FAST_FUNC;
9485 #endif
9486 static int readcmd(int, char **) FAST_FUNC;
9487 static int setcmd(int, char **) FAST_FUNC;
9488 static int shiftcmd(int, char **) FAST_FUNC;
9489 static int timescmd(int, char **) FAST_FUNC;
9490 static int trapcmd(int, char **) FAST_FUNC;
9491 static int umaskcmd(int, char **) FAST_FUNC;
9492 static int unsetcmd(int, char **) FAST_FUNC;
9493 static int ulimitcmd(int, char **) FAST_FUNC;
9494
9495 #define BUILTIN_NOSPEC          "0"
9496 #define BUILTIN_SPECIAL         "1"
9497 #define BUILTIN_REGULAR         "2"
9498 #define BUILTIN_SPEC_REG        "3"
9499 #define BUILTIN_ASSIGN          "4"
9500 #define BUILTIN_SPEC_ASSG       "5"
9501 #define BUILTIN_REG_ASSG        "6"
9502 #define BUILTIN_SPEC_REG_ASSG   "7"
9503
9504 /* Stubs for calling non-FAST_FUNC's */
9505 #if ENABLE_ASH_ECHO
9506 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9507 #endif
9508 #if ENABLE_ASH_PRINTF
9509 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9510 #endif
9511 #if ENABLE_ASH_TEST || BASH_TEST2
9512 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9513 #endif
9514
9515 /* Keep these in proper order since it is searched via bsearch() */
9516 static const struct builtincmd builtintab[] = {
9517         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9518         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9519 #if ENABLE_ASH_TEST
9520         { BUILTIN_REGULAR       "["       , testcmd    },
9521 #endif
9522 #if BASH_TEST2
9523         { BUILTIN_REGULAR       "[["      , testcmd    },
9524 #endif
9525 #if ENABLE_ASH_ALIAS
9526         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9527 #endif
9528 #if JOBS
9529         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9530 #endif
9531         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9532         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9533         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9534 #if ENABLE_ASH_CMDCMD
9535         { BUILTIN_REGULAR       "command" , commandcmd },
9536 #endif
9537         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9538 #if ENABLE_ASH_ECHO
9539         { BUILTIN_REGULAR       "echo"    , echocmd    },
9540 #endif
9541         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9542         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9543         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9544         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9545         { BUILTIN_REGULAR       "false"   , falsecmd   },
9546 #if JOBS
9547         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9548 #endif
9549 #if ENABLE_ASH_GETOPTS
9550         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9551 #endif
9552         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9553 #if ENABLE_ASH_HELP
9554         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9555 #endif
9556 #if MAX_HISTORY
9557         { BUILTIN_NOSPEC        "history" , historycmd },
9558 #endif
9559 #if JOBS
9560         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9561         { BUILTIN_REGULAR       "kill"    , killcmd    },
9562 #endif
9563 #if ENABLE_FEATURE_SH_MATH
9564         { BUILTIN_NOSPEC        "let"     , letcmd     },
9565 #endif
9566         { BUILTIN_ASSIGN        "local"   , localcmd   },
9567 #if ENABLE_ASH_PRINTF
9568         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9569 #endif
9570         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9571         { BUILTIN_REGULAR       "read"    , readcmd    },
9572         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9573         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9574         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9575         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9576 #if BASH_SOURCE
9577         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9578 #endif
9579 #if ENABLE_ASH_TEST
9580         { BUILTIN_REGULAR       "test"    , testcmd    },
9581 #endif
9582         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9583         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9584         { BUILTIN_REGULAR       "true"    , truecmd    },
9585         { BUILTIN_NOSPEC        "type"    , typecmd    },
9586         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9587         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9588 #if ENABLE_ASH_ALIAS
9589         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9590 #endif
9591         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9592         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9593 };
9594
9595 /* Should match the above table! */
9596 #define COMMANDCMD (builtintab + \
9597         /* . : */       2 + \
9598         /* [ */         1 * ENABLE_ASH_TEST + \
9599         /* [[ */        1 * BASH_TEST2 + \
9600         /* alias */     1 * ENABLE_ASH_ALIAS + \
9601         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9602         /* break cd cddir  */   3)
9603 #define EVALCMD (COMMANDCMD + \
9604         /* command */   1 * ENABLE_ASH_CMDCMD + \
9605         /* continue */  1 + \
9606         /* echo */      1 * ENABLE_ASH_ECHO + \
9607         0)
9608 #define EXECCMD (EVALCMD + \
9609         /* eval */      1)
9610
9611 /*
9612  * Search the table of builtin commands.
9613  */
9614 static int
9615 pstrcmp1(const void *a, const void *b)
9616 {
9617         return strcmp((char*)a, *(char**)b + 1);
9618 }
9619 static struct builtincmd *
9620 find_builtin(const char *name)
9621 {
9622         struct builtincmd *bp;
9623
9624         bp = bsearch(
9625                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9626                 pstrcmp1
9627         );
9628         return bp;
9629 }
9630
9631 /*
9632  * Execute a simple command.
9633  */
9634 static int
9635 isassignment(const char *p)
9636 {
9637         const char *q = endofname(p);
9638         if (p == q)
9639                 return 0;
9640         return *q == '=';
9641 }
9642 static int FAST_FUNC
9643 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9644 {
9645         /* Preserve exitstatus of a previous possible redirection
9646          * as POSIX mandates */
9647         return back_exitstatus;
9648 }
9649 static int
9650 evalcommand(union node *cmd, int flags)
9651 {
9652         static const struct builtincmd null_bltin = {
9653                 "\0\0", bltincmd /* why three NULs? */
9654         };
9655         struct stackmark smark;
9656         union node *argp;
9657         struct arglist arglist;
9658         struct arglist varlist;
9659         char **argv;
9660         int argc;
9661         const struct strlist *sp;
9662         struct cmdentry cmdentry;
9663         struct job *jp;
9664         char *lastarg;
9665         const char *path;
9666         int spclbltin;
9667         int status;
9668         char **nargv;
9669         struct builtincmd *bcmd;
9670         smallint cmd_is_exec;
9671         smallint pseudovarflag = 0;
9672
9673         /* First expand the arguments. */
9674         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9675         setstackmark(&smark);
9676         back_exitstatus = 0;
9677
9678         cmdentry.cmdtype = CMDBUILTIN;
9679         cmdentry.u.cmd = &null_bltin;
9680         varlist.lastp = &varlist.list;
9681         *varlist.lastp = NULL;
9682         arglist.lastp = &arglist.list;
9683         *arglist.lastp = NULL;
9684
9685         argc = 0;
9686         if (cmd->ncmd.args) {
9687                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9688                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9689         }
9690
9691         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9692                 struct strlist **spp;
9693
9694                 spp = arglist.lastp;
9695                 if (pseudovarflag && isassignment(argp->narg.text))
9696                         expandarg(argp, &arglist, EXP_VARTILDE);
9697                 else
9698                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9699
9700                 for (sp = *spp; sp; sp = sp->next)
9701                         argc++;
9702         }
9703
9704         /* Reserve one extra spot at the front for shellexec. */
9705         nargv = stalloc(sizeof(char *) * (argc + 2));
9706         argv = ++nargv;
9707         for (sp = arglist.list; sp; sp = sp->next) {
9708                 TRACE(("evalcommand arg: %s\n", sp->text));
9709                 *nargv++ = sp->text;
9710         }
9711         *nargv = NULL;
9712
9713         lastarg = NULL;
9714         if (iflag && funcnest == 0 && argc > 0)
9715                 lastarg = nargv[-1];
9716
9717         preverrout_fd = 2;
9718         expredir(cmd->ncmd.redirect);
9719         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9720
9721         path = vpath.var_text;
9722         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9723                 struct strlist **spp;
9724                 char *p;
9725
9726                 spp = varlist.lastp;
9727                 expandarg(argp, &varlist, EXP_VARTILDE);
9728
9729                 /*
9730                  * Modify the command lookup path, if a PATH= assignment
9731                  * is present
9732                  */
9733                 p = (*spp)->text;
9734                 if (varcmp(p, path) == 0)
9735                         path = p;
9736         }
9737
9738         /* Print the command if xflag is set. */
9739         if (xflag) {
9740                 const char *pfx = "";
9741
9742                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9743
9744                 sp = varlist.list;
9745                 while (sp) {
9746                         char *varval = sp->text;
9747                         char *eq = strchrnul(varval, '=');
9748                         if (*eq)
9749                                 eq++;
9750                         fdprintf(preverrout_fd, "%s%.*s%s",
9751                                 pfx,
9752                                 (int)(eq - varval), varval,
9753                                 maybe_single_quote(eq)
9754                         );
9755                         sp = sp->next;
9756                         pfx = " ";
9757                 }
9758
9759                 sp = arglist.list;
9760                 while (sp) {
9761                         fdprintf(preverrout_fd, "%s%s",
9762                                 pfx,
9763                                 /* always quote if matches reserved word: */
9764                                 findkwd(sp->text)
9765                                 ? single_quote(sp->text)
9766                                 : maybe_single_quote(sp->text)
9767                         );
9768                         sp = sp->next;
9769                         pfx = " ";
9770                 }
9771                 safe_write(preverrout_fd, "\n", 1);
9772         }
9773
9774         cmd_is_exec = 0;
9775         spclbltin = -1;
9776
9777         /* Now locate the command. */
9778         if (argc) {
9779                 int cmd_flag = DO_ERR;
9780 #if ENABLE_ASH_CMDCMD
9781                 const char *oldpath = path + 5;
9782 #endif
9783                 path += 5;
9784                 for (;;) {
9785                         find_command(argv[0], &cmdentry, cmd_flag, path);
9786                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9787                                 flush_stdout_stderr();
9788                                 status = 127;
9789                                 goto bail;
9790                         }
9791
9792                         /* implement bltin and command here */
9793                         if (cmdentry.cmdtype != CMDBUILTIN)
9794                                 break;
9795                         if (spclbltin < 0)
9796                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9797                         if (cmdentry.u.cmd == EXECCMD)
9798                                 cmd_is_exec = 1;
9799 #if ENABLE_ASH_CMDCMD
9800                         if (cmdentry.u.cmd == COMMANDCMD) {
9801                                 path = oldpath;
9802                                 nargv = parse_command_args(argv, &path);
9803                                 if (!nargv)
9804                                         break;
9805                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9806                                  * nargv => "PROG". path is updated if -p.
9807                                  */
9808                                 argc -= nargv - argv;
9809                                 argv = nargv;
9810                                 cmd_flag |= DO_NOFUNC;
9811                         } else
9812 #endif
9813                                 break;
9814                 }
9815         }
9816
9817         if (status) {
9818  bail:
9819                 exitstatus = status;
9820
9821                 /* We have a redirection error. */
9822                 if (spclbltin > 0)
9823                         raise_exception(EXERROR);
9824
9825                 goto out;
9826         }
9827
9828         /* Execute the command. */
9829         switch (cmdentry.cmdtype) {
9830         default: {
9831
9832 #if ENABLE_FEATURE_SH_NOFORK
9833 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9834  *     around run_nofork_applet() call.
9835  * (2) Should this check also be done in forkshell()?
9836  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9837  */
9838                 /* find_command() encodes applet_no as (-2 - applet_no) */
9839                 int applet_no = (- cmdentry.u.index - 2);
9840                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9841                         listsetvar(varlist.list, VEXPORT|VSTACK);
9842                         /* run <applet>_main() */
9843                         status = run_nofork_applet(applet_no, argv);
9844                         break;
9845                 }
9846 #endif
9847                 /* Can we avoid forking off? For example, very last command
9848                  * in a script or a subshell does not need forking,
9849                  * we can just exec it.
9850                  */
9851                 if (!(flags & EV_EXIT) || may_have_traps) {
9852                         /* No, forking off a child is necessary */
9853                         INT_OFF;
9854                         get_tty_state();
9855                         jp = makejob(/*cmd,*/ 1);
9856                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9857                                 /* parent */
9858                                 status = waitforjob(jp);
9859                                 INT_ON;
9860                                 TRACE(("forked child exited with %d\n", status));
9861                                 break;
9862                         }
9863                         /* child */
9864                         FORCE_INT_ON;
9865                         /* fall through to exec'ing external program */
9866                 }
9867                 listsetvar(varlist.list, VEXPORT|VSTACK);
9868                 shellexec(argv[0], argv, path, cmdentry.u.index);
9869                 /* NOTREACHED */
9870         } /* default */
9871         case CMDBUILTIN:
9872                 cmdenviron = varlist.list;
9873                 if (cmdenviron) {
9874                         struct strlist *list = cmdenviron;
9875                         int i = VNOSET;
9876                         if (spclbltin > 0 || argc == 0) {
9877                                 i = 0;
9878                                 if (cmd_is_exec && argc > 1)
9879                                         i = VEXPORT;
9880                         }
9881                         listsetvar(list, i);
9882                 }
9883                 /* Tight loop with builtins only:
9884                  * "while kill -0 $child; do true; done"
9885                  * will never exit even if $child died, unless we do this
9886                  * to reap the zombie and make kill detect that it's gone: */
9887                 dowait(DOWAIT_NONBLOCK, NULL);
9888
9889                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9890                         if (exception_type == EXERROR && spclbltin <= 0) {
9891                                 FORCE_INT_ON;
9892                                 goto readstatus;
9893                         }
9894  raise:
9895                         longjmp(exception_handler->loc, 1);
9896                 }
9897                 goto readstatus;
9898
9899         case CMDFUNCTION:
9900                 listsetvar(varlist.list, 0);
9901                 /* See above for the rationale */
9902                 dowait(DOWAIT_NONBLOCK, NULL);
9903                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9904                         goto raise;
9905  readstatus:
9906                 status = exitstatus;
9907                 break;
9908         } /* switch */
9909
9910  out:
9911         if (cmd->ncmd.redirect)
9912                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9913         if (lastarg) {
9914                 /* dsl: I think this is intended to be used to support
9915                  * '_' in 'vi' command mode during line editing...
9916                  * However I implemented that within libedit itself.
9917                  */
9918                 setvar0("_", lastarg);
9919         }
9920         popstackmark(&smark);
9921
9922         return status;
9923 }
9924
9925 static int
9926 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9927 {
9928         char *volatile savecmdname;
9929         struct jmploc *volatile savehandler;
9930         struct jmploc jmploc;
9931         int status;
9932         int i;
9933
9934         savecmdname = commandname;
9935         savehandler = exception_handler;
9936         i = setjmp(jmploc.loc);
9937         if (i)
9938                 goto cmddone;
9939         exception_handler = &jmploc;
9940         commandname = argv[0];
9941         argptr = argv + 1;
9942         optptr = NULL;                  /* initialize nextopt */
9943         if (cmd == EVALCMD)
9944                 status = evalcmd(argc, argv, flags);
9945         else
9946                 status = (*cmd->builtin)(argc, argv);
9947         flush_stdout_stderr();
9948         status |= ferror(stdout);
9949         exitstatus = status;
9950  cmddone:
9951         clearerr(stdout);
9952         commandname = savecmdname;
9953         exception_handler = savehandler;
9954
9955         return i;
9956 }
9957
9958 static int
9959 goodname(const char *p)
9960 {
9961         return endofname(p)[0] == '\0';
9962 }
9963
9964
9965 /*
9966  * Search for a command.  This is called before we fork so that the
9967  * location of the command will be available in the parent as well as
9968  * the child.  The check for "goodname" is an overly conservative
9969  * check that the name will not be subject to expansion.
9970  */
9971 static void
9972 prehash(union node *n)
9973 {
9974         struct cmdentry entry;
9975
9976         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9977                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9978 }
9979
9980
9981 /* ============ Builtin commands
9982  *
9983  * Builtin commands whose functions are closely tied to evaluation
9984  * are implemented here.
9985  */
9986
9987 /*
9988  * Handle break and continue commands.  Break, continue, and return are
9989  * all handled by setting the evalskip flag.  The evaluation routines
9990  * above all check this flag, and if it is set they start skipping
9991  * commands rather than executing them.  The variable skipcount is
9992  * the number of loops to break/continue, or the number of function
9993  * levels to return.  (The latter is always 1.)  It should probably
9994  * be an error to break out of more loops than exist, but it isn't
9995  * in the standard shell so we don't make it one here.
9996  */
9997 static int FAST_FUNC
9998 breakcmd(int argc UNUSED_PARAM, char **argv)
9999 {
10000         int n = argv[1] ? number(argv[1]) : 1;
10001
10002         if (n <= 0)
10003                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10004         if (n > loopnest)
10005                 n = loopnest;
10006         if (n > 0) {
10007                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10008                 skipcount = n;
10009         }
10010         return 0;
10011 }
10012
10013
10014 /*
10015  * This implements the input routines used by the parser.
10016  */
10017
10018 enum {
10019         INPUT_PUSH_FILE = 1,
10020         INPUT_NOFILE_OK = 2,
10021 };
10022
10023 static smallint checkkwd;
10024 /* values of checkkwd variable */
10025 #define CHKALIAS        0x1
10026 #define CHKKWD          0x2
10027 #define CHKNL           0x4
10028
10029 /*
10030  * Push a string back onto the input at this current parsefile level.
10031  * We handle aliases this way.
10032  */
10033 #if !ENABLE_ASH_ALIAS
10034 #define pushstring(s, ap) pushstring(s)
10035 #endif
10036 static void
10037 pushstring(char *s, struct alias *ap)
10038 {
10039         struct strpush *sp;
10040         int len;
10041
10042         len = strlen(s);
10043         INT_OFF;
10044         if (g_parsefile->strpush) {
10045                 sp = ckzalloc(sizeof(*sp));
10046                 sp->prev = g_parsefile->strpush;
10047         } else {
10048                 sp = &(g_parsefile->basestrpush);
10049         }
10050         g_parsefile->strpush = sp;
10051         sp->prev_string = g_parsefile->next_to_pgetc;
10052         sp->prev_left_in_line = g_parsefile->left_in_line;
10053         sp->unget = g_parsefile->unget;
10054         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10055 #if ENABLE_ASH_ALIAS
10056         sp->ap = ap;
10057         if (ap) {
10058                 ap->flag |= ALIASINUSE;
10059                 sp->string = s;
10060         }
10061 #endif
10062         g_parsefile->next_to_pgetc = s;
10063         g_parsefile->left_in_line = len;
10064         g_parsefile->unget = 0;
10065         INT_ON;
10066 }
10067
10068 static void
10069 popstring(void)
10070 {
10071         struct strpush *sp = g_parsefile->strpush;
10072
10073         INT_OFF;
10074 #if ENABLE_ASH_ALIAS
10075         if (sp->ap) {
10076                 if (g_parsefile->next_to_pgetc[-1] == ' '
10077                  || g_parsefile->next_to_pgetc[-1] == '\t'
10078                 ) {
10079                         checkkwd |= CHKALIAS;
10080                 }
10081                 if (sp->string != sp->ap->val) {
10082                         free(sp->string);
10083                 }
10084                 sp->ap->flag &= ~ALIASINUSE;
10085                 if (sp->ap->flag & ALIASDEAD) {
10086                         unalias(sp->ap->name);
10087                 }
10088         }
10089 #endif
10090         g_parsefile->next_to_pgetc = sp->prev_string;
10091         g_parsefile->left_in_line = sp->prev_left_in_line;
10092         g_parsefile->unget = sp->unget;
10093         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10094         g_parsefile->strpush = sp->prev;
10095         if (sp != &(g_parsefile->basestrpush))
10096                 free(sp);
10097         INT_ON;
10098 }
10099
10100 static int
10101 preadfd(void)
10102 {
10103         int nr;
10104         char *buf = g_parsefile->buf;
10105
10106         g_parsefile->next_to_pgetc = buf;
10107 #if ENABLE_FEATURE_EDITING
10108  retry:
10109         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10110                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10111         else {
10112                 int timeout = -1;
10113 # if ENABLE_ASH_IDLE_TIMEOUT
10114                 if (iflag) {
10115                         const char *tmout_var = lookupvar("TMOUT");
10116                         if (tmout_var) {
10117                                 timeout = atoi(tmout_var) * 1000;
10118                                 if (timeout <= 0)
10119                                         timeout = -1;
10120                         }
10121                 }
10122 # endif
10123 # if ENABLE_FEATURE_TAB_COMPLETION
10124                 line_input_state->path_lookup = pathval();
10125 # endif
10126                 reinit_unicode_for_ash();
10127                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10128                 if (nr == 0) {
10129                         /* ^C pressed, "convert" to SIGINT */
10130                         write(STDOUT_FILENO, "^C", 2);
10131                         if (trap[SIGINT]) {
10132                                 buf[0] = '\n';
10133                                 buf[1] = '\0';
10134                                 raise(SIGINT);
10135                                 return 1;
10136                         }
10137                         exitstatus = 128 + SIGINT;
10138                         bb_putchar('\n');
10139                         goto retry;
10140                 }
10141                 if (nr < 0) {
10142                         if (errno == 0) {
10143                                 /* Ctrl+D pressed */
10144                                 nr = 0;
10145                         }
10146 # if ENABLE_ASH_IDLE_TIMEOUT
10147                         else if (errno == EAGAIN && timeout > 0) {
10148                                 puts("\007timed out waiting for input: auto-logout");
10149                                 exitshell();
10150                         }
10151 # endif
10152                 }
10153         }
10154 #else
10155         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10156 #endif
10157
10158 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10159         if (nr < 0) {
10160                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10161                         int flags = fcntl(0, F_GETFL);
10162                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10163                                 flags &= ~O_NONBLOCK;
10164                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10165                                         out2str("sh: turning off NDELAY mode\n");
10166                                         goto retry;
10167                                 }
10168                         }
10169                 }
10170         }
10171 #endif
10172         return nr;
10173 }
10174
10175 /*
10176  * Refill the input buffer and return the next input character:
10177  *
10178  * 1) If a string was pushed back on the input, pop it;
10179  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10180  *    or we are reading from a string so we can't refill the buffer,
10181  *    return EOF.
10182  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10183  * 4) Process input up to the next newline, deleting nul characters.
10184  */
10185 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10186 #define pgetc_debug(...) ((void)0)
10187 static int pgetc(void);
10188 static int
10189 preadbuffer(void)
10190 {
10191         char *q;
10192         int more;
10193
10194         if (g_parsefile->strpush) {
10195 #if ENABLE_ASH_ALIAS
10196                 if (g_parsefile->left_in_line == -1
10197                  && g_parsefile->strpush->ap
10198                  && g_parsefile->next_to_pgetc[-1] != ' '
10199                  && g_parsefile->next_to_pgetc[-1] != '\t'
10200                 ) {
10201                         pgetc_debug("preadbuffer PEOA");
10202                         return PEOA;
10203                 }
10204 #endif
10205                 popstring();
10206                 return pgetc();
10207         }
10208         /* on both branches above g_parsefile->left_in_line < 0.
10209          * "pgetc" needs refilling.
10210          */
10211
10212         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10213          * pungetc() may increment it a few times.
10214          * Assuming it won't increment it to less than -90.
10215          */
10216         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10217                 pgetc_debug("preadbuffer PEOF1");
10218                 /* even in failure keep left_in_line and next_to_pgetc
10219                  * in lock step, for correct multi-layer pungetc.
10220                  * left_in_line was decremented before preadbuffer(),
10221                  * must inc next_to_pgetc: */
10222                 g_parsefile->next_to_pgetc++;
10223                 return PEOF;
10224         }
10225
10226         more = g_parsefile->left_in_buffer;
10227         if (more <= 0) {
10228                 flush_stdout_stderr();
10229  again:
10230                 more = preadfd();
10231                 if (more <= 0) {
10232                         /* don't try reading again */
10233                         g_parsefile->left_in_line = -99;
10234                         pgetc_debug("preadbuffer PEOF2");
10235                         g_parsefile->next_to_pgetc++;
10236                         return PEOF;
10237                 }
10238         }
10239
10240         /* Find out where's the end of line.
10241          * Set g_parsefile->left_in_line
10242          * and g_parsefile->left_in_buffer acordingly.
10243          * NUL chars are deleted.
10244          */
10245         q = g_parsefile->next_to_pgetc;
10246         for (;;) {
10247                 char c;
10248
10249                 more--;
10250
10251                 c = *q;
10252                 if (c == '\0') {
10253                         memmove(q, q + 1, more);
10254                 } else {
10255                         q++;
10256                         if (c == '\n') {
10257                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10258                                 break;
10259                         }
10260                 }
10261
10262                 if (more <= 0) {
10263                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10264                         if (g_parsefile->left_in_line < 0)
10265                                 goto again;
10266                         break;
10267                 }
10268         }
10269         g_parsefile->left_in_buffer = more;
10270
10271         if (vflag) {
10272                 char save = *q;
10273                 *q = '\0';
10274                 out2str(g_parsefile->next_to_pgetc);
10275                 *q = save;
10276         }
10277
10278         pgetc_debug("preadbuffer at %d:%p'%s'",
10279                         g_parsefile->left_in_line,
10280                         g_parsefile->next_to_pgetc,
10281                         g_parsefile->next_to_pgetc);
10282         return (unsigned char)*g_parsefile->next_to_pgetc++;
10283 }
10284
10285 static void
10286 nlprompt(void)
10287 {
10288         g_parsefile->linno++;
10289         setprompt_if(doprompt, 2);
10290 }
10291 static void
10292 nlnoprompt(void)
10293 {
10294         g_parsefile->linno++;
10295         needprompt = doprompt;
10296 }
10297
10298 static int
10299 pgetc(void)
10300 {
10301         int c;
10302
10303         pgetc_debug("pgetc at %d:%p'%s'",
10304                         g_parsefile->left_in_line,
10305                         g_parsefile->next_to_pgetc,
10306                         g_parsefile->next_to_pgetc);
10307         if (g_parsefile->unget)
10308                 return g_parsefile->lastc[--g_parsefile->unget];
10309
10310         if (--g_parsefile->left_in_line >= 0)
10311                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10312         else
10313                 c = preadbuffer();
10314
10315         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10316         g_parsefile->lastc[0] = c;
10317
10318         return c;
10319 }
10320
10321 #if ENABLE_ASH_ALIAS
10322 static int
10323 pgetc_without_PEOA(void)
10324 {
10325         int c;
10326         do {
10327                 pgetc_debug("pgetc at %d:%p'%s'",
10328                                 g_parsefile->left_in_line,
10329                                 g_parsefile->next_to_pgetc,
10330                                 g_parsefile->next_to_pgetc);
10331                 c = pgetc();
10332         } while (c == PEOA);
10333         return c;
10334 }
10335 #else
10336 # define pgetc_without_PEOA() pgetc()
10337 #endif
10338
10339 /*
10340  * Read a line from the script.
10341  */
10342 static char *
10343 pfgets(char *line, int len)
10344 {
10345         char *p = line;
10346         int nleft = len;
10347         int c;
10348
10349         while (--nleft > 0) {
10350                 c = pgetc_without_PEOA();
10351                 if (c == PEOF) {
10352                         if (p == line)
10353                                 return NULL;
10354                         break;
10355                 }
10356                 *p++ = c;
10357                 if (c == '\n')
10358                         break;
10359         }
10360         *p = '\0';
10361         return line;
10362 }
10363
10364 /*
10365  * Undo a call to pgetc.  Only two characters may be pushed back.
10366  * PEOF may be pushed back.
10367  */
10368 static void
10369 pungetc(void)
10370 {
10371         g_parsefile->unget++;
10372 }
10373
10374 /* This one eats backslash+newline */
10375 static int
10376 pgetc_eatbnl(void)
10377 {
10378         int c;
10379
10380         while ((c = pgetc()) == '\\') {
10381                 if (pgetc() != '\n') {
10382                         pungetc();
10383                         break;
10384                 }
10385
10386                 nlprompt();
10387         }
10388
10389         return c;
10390 }
10391
10392 /*
10393  * To handle the "." command, a stack of input files is used.  Pushfile
10394  * adds a new entry to the stack and popfile restores the previous level.
10395  */
10396 static void
10397 pushfile(void)
10398 {
10399         struct parsefile *pf;
10400
10401         pf = ckzalloc(sizeof(*pf));
10402         pf->prev = g_parsefile;
10403         pf->pf_fd = -1;
10404         /*pf->strpush = NULL; - ckzalloc did it */
10405         /*pf->basestrpush.prev = NULL;*/
10406         /*pf->unget = 0;*/
10407         g_parsefile = pf;
10408 }
10409
10410 static void
10411 popfile(void)
10412 {
10413         struct parsefile *pf = g_parsefile;
10414
10415         if (pf == &basepf)
10416                 return;
10417
10418         INT_OFF;
10419         if (pf->pf_fd >= 0)
10420                 close(pf->pf_fd);
10421         free(pf->buf);
10422         while (pf->strpush)
10423                 popstring();
10424         g_parsefile = pf->prev;
10425         free(pf);
10426         INT_ON;
10427 }
10428
10429 /*
10430  * Return to top level.
10431  */
10432 static void
10433 popallfiles(void)
10434 {
10435         while (g_parsefile != &basepf)
10436                 popfile();
10437 }
10438
10439 /*
10440  * Close the file(s) that the shell is reading commands from.  Called
10441  * after a fork is done.
10442  */
10443 static void
10444 closescript(void)
10445 {
10446         popallfiles();
10447         if (g_parsefile->pf_fd > 0) {
10448                 close(g_parsefile->pf_fd);
10449                 g_parsefile->pf_fd = 0;
10450         }
10451 }
10452
10453 /*
10454  * Like setinputfile, but takes an open file descriptor.  Call this with
10455  * interrupts off.
10456  */
10457 static void
10458 setinputfd(int fd, int push)
10459 {
10460         if (push) {
10461                 pushfile();
10462                 g_parsefile->buf = NULL;
10463         }
10464         g_parsefile->pf_fd = fd;
10465         if (g_parsefile->buf == NULL)
10466                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10467         g_parsefile->left_in_buffer = 0;
10468         g_parsefile->left_in_line = 0;
10469         g_parsefile->linno = 1;
10470 }
10471
10472 /*
10473  * Set the input to take input from a file.  If push is set, push the
10474  * old input onto the stack first.
10475  */
10476 static int
10477 setinputfile(const char *fname, int flags)
10478 {
10479         int fd;
10480
10481         INT_OFF;
10482         fd = open(fname, O_RDONLY);
10483         if (fd < 0) {
10484                 if (flags & INPUT_NOFILE_OK)
10485                         goto out;
10486                 exitstatus = 127;
10487                 ash_msg_and_raise_error("can't open '%s'", fname);
10488         }
10489         if (fd < 10)
10490                 fd = savefd(fd);
10491         else
10492                 close_on_exec_on(fd);
10493         setinputfd(fd, flags & INPUT_PUSH_FILE);
10494  out:
10495         INT_ON;
10496         return fd;
10497 }
10498
10499 /*
10500  * Like setinputfile, but takes input from a string.
10501  */
10502 static void
10503 setinputstring(char *string)
10504 {
10505         INT_OFF;
10506         pushfile();
10507         g_parsefile->next_to_pgetc = string;
10508         g_parsefile->left_in_line = strlen(string);
10509         g_parsefile->buf = NULL;
10510         g_parsefile->linno = 1;
10511         INT_ON;
10512 }
10513
10514
10515 /*
10516  * Routines to check for mail.
10517  */
10518
10519 #if ENABLE_ASH_MAIL
10520
10521 /* Hash of mtimes of mailboxes */
10522 static unsigned mailtime_hash;
10523 /* Set if MAIL or MAILPATH is changed. */
10524 static smallint mail_var_path_changed;
10525
10526 /*
10527  * Print appropriate message(s) if mail has arrived.
10528  * If mail_var_path_changed is set,
10529  * then the value of MAIL has mail_var_path_changed,
10530  * so we just update the values.
10531  */
10532 static void
10533 chkmail(void)
10534 {
10535         const char *mpath;
10536         char *p;
10537         char *q;
10538         unsigned new_hash;
10539         struct stackmark smark;
10540         struct stat statb;
10541
10542         setstackmark(&smark);
10543         mpath = mpathset() ? mpathval() : mailval();
10544         new_hash = 0;
10545         for (;;) {
10546                 p = path_advance(&mpath, nullstr);
10547                 if (p == NULL)
10548                         break;
10549                 if (*p == '\0')
10550                         continue;
10551                 for (q = p; *q; q++)
10552                         continue;
10553 #if DEBUG
10554                 if (q[-1] != '/')
10555                         abort();
10556 #endif
10557                 q[-1] = '\0';                   /* delete trailing '/' */
10558                 if (stat(p, &statb) < 0) {
10559                         continue;
10560                 }
10561                 /* Very simplistic "hash": just a sum of all mtimes */
10562                 new_hash += (unsigned)statb.st_mtime;
10563         }
10564         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10565                 if (mailtime_hash != 0)
10566                         out2str("you have mail\n");
10567                 mailtime_hash = new_hash;
10568         }
10569         mail_var_path_changed = 0;
10570         popstackmark(&smark);
10571 }
10572
10573 static void FAST_FUNC
10574 changemail(const char *val UNUSED_PARAM)
10575 {
10576         mail_var_path_changed = 1;
10577 }
10578
10579 #endif /* ASH_MAIL */
10580
10581
10582 /* ============ ??? */
10583
10584 /*
10585  * Set the shell parameters.
10586  */
10587 static void
10588 setparam(char **argv)
10589 {
10590         char **newparam;
10591         char **ap;
10592         int nparam;
10593
10594         for (nparam = 0; argv[nparam]; nparam++)
10595                 continue;
10596         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10597         while (*argv) {
10598                 *ap++ = ckstrdup(*argv++);
10599         }
10600         *ap = NULL;
10601         freeparam(&shellparam);
10602         shellparam.malloced = 1;
10603         shellparam.nparam = nparam;
10604         shellparam.p = newparam;
10605 #if ENABLE_ASH_GETOPTS
10606         shellparam.optind = 1;
10607         shellparam.optoff = -1;
10608 #endif
10609 }
10610
10611 /*
10612  * Process shell options.  The global variable argptr contains a pointer
10613  * to the argument list; we advance it past the options.
10614  *
10615  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10616  * For a non-interactive shell, an error condition encountered
10617  * by a special built-in ... shall cause the shell to write a diagnostic message
10618  * to standard error and exit as shown in the following table:
10619  * Error                                           Special Built-In
10620  * ...
10621  * Utility syntax error (option or operand error)  Shall exit
10622  * ...
10623  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10624  * we see that bash does not do that (set "finishes" with error code 1 instead,
10625  * and shell continues), and people rely on this behavior!
10626  * Testcase:
10627  * set -o barfoo 2>/dev/null
10628  * echo $?
10629  *
10630  * Oh well. Let's mimic that.
10631  */
10632 static int
10633 plus_minus_o(char *name, int val)
10634 {
10635         int i;
10636
10637         if (name) {
10638                 for (i = 0; i < NOPTS; i++) {
10639                         if (strcmp(name, optnames(i)) == 0) {
10640                                 optlist[i] = val;
10641                                 return 0;
10642                         }
10643                 }
10644                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10645                 return 1;
10646         }
10647         for (i = 0; i < NOPTS; i++) {
10648                 if (val) {
10649                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10650                 } else {
10651                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10652                 }
10653         }
10654         return 0;
10655 }
10656 static void
10657 setoption(int flag, int val)
10658 {
10659         int i;
10660
10661         for (i = 0; i < NOPTS; i++) {
10662                 if (optletters(i) == flag) {
10663                         optlist[i] = val;
10664                         return;
10665                 }
10666         }
10667         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10668         /* NOTREACHED */
10669 }
10670 static int
10671 options(int cmdline)
10672 {
10673         char *p;
10674         int val;
10675         int c;
10676
10677         if (cmdline)
10678                 minusc = NULL;
10679         while ((p = *argptr) != NULL) {
10680                 c = *p++;
10681                 if (c != '-' && c != '+')
10682                         break;
10683                 argptr++;
10684                 val = 0; /* val = 0 if c == '+' */
10685                 if (c == '-') {
10686                         val = 1;
10687                         if (p[0] == '\0' || LONE_DASH(p)) {
10688                                 if (!cmdline) {
10689                                         /* "-" means turn off -x and -v */
10690                                         if (p[0] == '\0')
10691                                                 xflag = vflag = 0;
10692                                         /* "--" means reset params */
10693                                         else if (*argptr == NULL)
10694                                                 setparam(argptr);
10695                                 }
10696                                 break;    /* "-" or "--" terminates options */
10697                         }
10698                 }
10699                 /* first char was + or - */
10700                 while ((c = *p++) != '\0') {
10701                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10702                         if (c == 'c' && cmdline) {
10703                                 minusc = p;     /* command is after shell args */
10704                         } else if (c == 'o') {
10705                                 if (plus_minus_o(*argptr, val)) {
10706                                         /* it already printed err message */
10707                                         return 1; /* error */
10708                                 }
10709                                 if (*argptr)
10710                                         argptr++;
10711                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10712                                 isloginsh = 1;
10713                         /* bash does not accept +-login, we also won't */
10714                         } else if (cmdline && val && (c == '-')) { /* long options */
10715                                 if (strcmp(p, "login") == 0)
10716                                         isloginsh = 1;
10717                                 break;
10718                         } else {
10719                                 setoption(c, val);
10720                         }
10721                 }
10722         }
10723         return 0;
10724 }
10725
10726 /*
10727  * The shift builtin command.
10728  */
10729 static int FAST_FUNC
10730 shiftcmd(int argc UNUSED_PARAM, char **argv)
10731 {
10732         int n;
10733         char **ap1, **ap2;
10734
10735         n = 1;
10736         if (argv[1])
10737                 n = number(argv[1]);
10738         if (n > shellparam.nparam)
10739                 n = 0; /* bash compat, was = shellparam.nparam; */
10740         INT_OFF;
10741         shellparam.nparam -= n;
10742         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10743                 if (shellparam.malloced)
10744                         free(*ap1);
10745         }
10746         ap2 = shellparam.p;
10747         while ((*ap2++ = *ap1++) != NULL)
10748                 continue;
10749 #if ENABLE_ASH_GETOPTS
10750         shellparam.optind = 1;
10751         shellparam.optoff = -1;
10752 #endif
10753         INT_ON;
10754         return 0;
10755 }
10756
10757 /*
10758  * POSIX requires that 'set' (but not export or readonly) output the
10759  * variables in lexicographic order - by the locale's collating order (sigh).
10760  * Maybe we could keep them in an ordered balanced binary tree
10761  * instead of hashed lists.
10762  * For now just roll 'em through qsort for printing...
10763  */
10764 static int
10765 showvars(const char *sep_prefix, int on, int off)
10766 {
10767         const char *sep;
10768         char **ep, **epend;
10769
10770         ep = listvars(on, off, &epend);
10771         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10772
10773         sep = *sep_prefix ? " " : sep_prefix;
10774
10775         for (; ep < epend; ep++) {
10776                 const char *p;
10777                 const char *q;
10778
10779                 p = strchrnul(*ep, '=');
10780                 q = nullstr;
10781                 if (*p)
10782                         q = single_quote(++p);
10783                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10784         }
10785         return 0;
10786 }
10787
10788 /*
10789  * The set command builtin.
10790  */
10791 static int FAST_FUNC
10792 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10793 {
10794         int retval;
10795
10796         if (!argv[1])
10797                 return showvars(nullstr, 0, VUNSET);
10798
10799         INT_OFF;
10800         retval = options(/*cmdline:*/ 0);
10801         if (retval == 0) { /* if no parse error... */
10802                 optschanged();
10803                 if (*argptr != NULL) {
10804                         setparam(argptr);
10805                 }
10806         }
10807         INT_ON;
10808         return retval;
10809 }
10810
10811 #if ENABLE_ASH_RANDOM_SUPPORT
10812 static void FAST_FUNC
10813 change_random(const char *value)
10814 {
10815         uint32_t t;
10816
10817         if (value == NULL) {
10818                 /* "get", generate */
10819                 t = next_random(&random_gen);
10820                 /* set without recursion */
10821                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10822                 vrandom.flags &= ~VNOFUNC;
10823         } else {
10824                 /* set/reset */
10825                 t = strtoul(value, NULL, 10);
10826                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10827         }
10828 }
10829 #endif
10830
10831 #if ENABLE_ASH_GETOPTS
10832 static int
10833 getopts(char *optstr, char *optvar, char **optfirst)
10834 {
10835         char *p, *q;
10836         char c = '?';
10837         int done = 0;
10838         char sbuf[2];
10839         char **optnext;
10840         int ind = shellparam.optind;
10841         int off = shellparam.optoff;
10842
10843         sbuf[1] = '\0';
10844
10845         shellparam.optind = -1;
10846         optnext = optfirst + ind - 1;
10847
10848         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10849                 p = NULL;
10850         else
10851                 p = optnext[-1] + off;
10852         if (p == NULL || *p == '\0') {
10853                 /* Current word is done, advance */
10854                 p = *optnext;
10855                 if (p == NULL || *p != '-' || *++p == '\0') {
10856  atend:
10857                         p = NULL;
10858                         done = 1;
10859                         goto out;
10860                 }
10861                 optnext++;
10862                 if (LONE_DASH(p))        /* check for "--" */
10863                         goto atend;
10864         }
10865
10866         c = *p++;
10867         for (q = optstr; *q != c;) {
10868                 if (*q == '\0') {
10869                         if (optstr[0] == ':') {
10870                                 sbuf[0] = c;
10871                                 /*sbuf[1] = '\0'; - already is */
10872                                 setvar0("OPTARG", sbuf);
10873                         } else {
10874                                 fprintf(stderr, "Illegal option -%c\n", c);
10875                                 unsetvar("OPTARG");
10876                         }
10877                         c = '?';
10878                         goto out;
10879                 }
10880                 if (*++q == ':')
10881                         q++;
10882         }
10883
10884         if (*++q == ':') {
10885                 if (*p == '\0' && (p = *optnext) == NULL) {
10886                         if (optstr[0] == ':') {
10887                                 sbuf[0] = c;
10888                                 /*sbuf[1] = '\0'; - already is */
10889                                 setvar0("OPTARG", sbuf);
10890                                 c = ':';
10891                         } else {
10892                                 fprintf(stderr, "No arg for -%c option\n", c);
10893                                 unsetvar("OPTARG");
10894                                 c = '?';
10895                         }
10896                         goto out;
10897                 }
10898
10899                 if (p == *optnext)
10900                         optnext++;
10901                 setvar0("OPTARG", p);
10902                 p = NULL;
10903         } else
10904                 setvar0("OPTARG", nullstr);
10905  out:
10906         ind = optnext - optfirst + 1;
10907         setvar("OPTIND", itoa(ind), VNOFUNC);
10908         sbuf[0] = c;
10909         /*sbuf[1] = '\0'; - already is */
10910         setvar0(optvar, sbuf);
10911
10912         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10913         shellparam.optind = ind;
10914
10915         return done;
10916 }
10917
10918 /*
10919  * The getopts builtin.  Shellparam.optnext points to the next argument
10920  * to be processed.  Shellparam.optptr points to the next character to
10921  * be processed in the current argument.  If shellparam.optnext is NULL,
10922  * then it's the first time getopts has been called.
10923  */
10924 static int FAST_FUNC
10925 getoptscmd(int argc, char **argv)
10926 {
10927         char **optbase;
10928
10929         if (argc < 3)
10930                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10931         if (argc == 3) {
10932                 optbase = shellparam.p;
10933                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10934                         shellparam.optind = 1;
10935                         shellparam.optoff = -1;
10936                 }
10937         } else {
10938                 optbase = &argv[3];
10939                 if ((unsigned)shellparam.optind > argc - 2) {
10940                         shellparam.optind = 1;
10941                         shellparam.optoff = -1;
10942                 }
10943         }
10944
10945         return getopts(argv[1], argv[2], optbase);
10946 }
10947 #endif /* ASH_GETOPTS */
10948
10949
10950 /* ============ Shell parser */
10951
10952 struct heredoc {
10953         struct heredoc *next;   /* next here document in list */
10954         union node *here;       /* redirection node */
10955         char *eofmark;          /* string indicating end of input */
10956         smallint striptabs;     /* if set, strip leading tabs */
10957 };
10958
10959 static smallint tokpushback;           /* last token pushed back */
10960 static smallint quoteflag;             /* set if (part of) last token was quoted */
10961 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10962 static struct heredoc *heredoclist;    /* list of here documents to read */
10963 static char *wordtext;                 /* text of last word returned by readtoken */
10964 static struct nodelist *backquotelist;
10965 static union node *redirnode;
10966 static struct heredoc *heredoc;
10967
10968 static const char *
10969 tokname(char *buf, int tok)
10970 {
10971         if (tok < TSEMI)
10972                 return tokname_array[tok];
10973         sprintf(buf, "\"%s\"", tokname_array[tok]);
10974         return buf;
10975 }
10976
10977 /* raise_error_unexpected_syntax:
10978  * Called when an unexpected token is read during the parse.  The argument
10979  * is the token that is expected, or -1 if more than one type of token can
10980  * occur at this point.
10981  */
10982 static void raise_error_unexpected_syntax(int) NORETURN;
10983 static void
10984 raise_error_unexpected_syntax(int token)
10985 {
10986         char msg[64];
10987         char buf[16];
10988         int l;
10989
10990         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10991         if (token >= 0)
10992                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10993         raise_error_syntax(msg);
10994         /* NOTREACHED */
10995 }
10996
10997 #define EOFMARKLEN 79
10998
10999 /* parsing is heavily cross-recursive, need these forward decls */
11000 static union node *andor(void);
11001 static union node *pipeline(void);
11002 static union node *parse_command(void);
11003 static void parseheredoc(void);
11004 static int peektoken(void);
11005 static int readtoken(void);
11006
11007 static union node *
11008 list(int nlflag)
11009 {
11010         union node *n1, *n2, *n3;
11011         int tok;
11012
11013         n1 = NULL;
11014         for (;;) {
11015                 switch (peektoken()) {
11016                 case TNL:
11017                         if (!(nlflag & 1))
11018                                 break;
11019                         parseheredoc();
11020                         return n1;
11021
11022                 case TEOF:
11023                         if (!n1 && (nlflag & 1))
11024                                 n1 = NODE_EOF;
11025                         parseheredoc();
11026                         return n1;
11027                 }
11028
11029                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11030                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11031                         return n1;
11032                 nlflag |= 2;
11033
11034                 n2 = andor();
11035                 tok = readtoken();
11036                 if (tok == TBACKGND) {
11037                         if (n2->type == NPIPE) {
11038                                 n2->npipe.pipe_backgnd = 1;
11039                         } else {
11040                                 if (n2->type != NREDIR) {
11041                                         n3 = stzalloc(sizeof(struct nredir));
11042                                         n3->nredir.n = n2;
11043                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11044                                         n2 = n3;
11045                                 }
11046                                 n2->type = NBACKGND;
11047                         }
11048                 }
11049                 if (n1 == NULL) {
11050                         n1 = n2;
11051                 } else {
11052                         n3 = stzalloc(sizeof(struct nbinary));
11053                         n3->type = NSEMI;
11054                         n3->nbinary.ch1 = n1;
11055                         n3->nbinary.ch2 = n2;
11056                         n1 = n3;
11057                 }
11058                 switch (tok) {
11059                 case TNL:
11060                 case TEOF:
11061                         tokpushback = 1;
11062                         /* fall through */
11063                 case TBACKGND:
11064                 case TSEMI:
11065                         break;
11066                 default:
11067                         if ((nlflag & 1))
11068                                 raise_error_unexpected_syntax(-1);
11069                         tokpushback = 1;
11070                         return n1;
11071                 }
11072         }
11073 }
11074
11075 static union node *
11076 andor(void)
11077 {
11078         union node *n1, *n2, *n3;
11079         int t;
11080
11081         n1 = pipeline();
11082         for (;;) {
11083                 t = readtoken();
11084                 if (t == TAND) {
11085                         t = NAND;
11086                 } else if (t == TOR) {
11087                         t = NOR;
11088                 } else {
11089                         tokpushback = 1;
11090                         return n1;
11091                 }
11092                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11093                 n2 = pipeline();
11094                 n3 = stzalloc(sizeof(struct nbinary));
11095                 n3->type = t;
11096                 n3->nbinary.ch1 = n1;
11097                 n3->nbinary.ch2 = n2;
11098                 n1 = n3;
11099         }
11100 }
11101
11102 static union node *
11103 pipeline(void)
11104 {
11105         union node *n1, *n2, *pipenode;
11106         struct nodelist *lp, *prev;
11107         int negate;
11108
11109         negate = 0;
11110         TRACE(("pipeline: entered\n"));
11111         if (readtoken() == TNOT) {
11112                 negate = !negate;
11113                 checkkwd = CHKKWD | CHKALIAS;
11114         } else
11115                 tokpushback = 1;
11116         n1 = parse_command();
11117         if (readtoken() == TPIPE) {
11118                 pipenode = stzalloc(sizeof(struct npipe));
11119                 pipenode->type = NPIPE;
11120                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11121                 lp = stzalloc(sizeof(struct nodelist));
11122                 pipenode->npipe.cmdlist = lp;
11123                 lp->n = n1;
11124                 do {
11125                         prev = lp;
11126                         lp = stzalloc(sizeof(struct nodelist));
11127                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11128                         lp->n = parse_command();
11129                         prev->next = lp;
11130                 } while (readtoken() == TPIPE);
11131                 lp->next = NULL;
11132                 n1 = pipenode;
11133         }
11134         tokpushback = 1;
11135         if (negate) {
11136                 n2 = stzalloc(sizeof(struct nnot));
11137                 n2->type = NNOT;
11138                 n2->nnot.com = n1;
11139                 return n2;
11140         }
11141         return n1;
11142 }
11143
11144 static union node *
11145 makename(void)
11146 {
11147         union node *n;
11148
11149         n = stzalloc(sizeof(struct narg));
11150         n->type = NARG;
11151         /*n->narg.next = NULL; - stzalloc did it */
11152         n->narg.text = wordtext;
11153         n->narg.backquote = backquotelist;
11154         return n;
11155 }
11156
11157 static void
11158 fixredir(union node *n, const char *text, int err)
11159 {
11160         int fd;
11161
11162         TRACE(("Fix redir %s %d\n", text, err));
11163         if (!err)
11164                 n->ndup.vname = NULL;
11165
11166         fd = bb_strtou(text, NULL, 10);
11167         if (!errno && fd >= 0)
11168                 n->ndup.dupfd = fd;
11169         else if (LONE_DASH(text))
11170                 n->ndup.dupfd = -1;
11171         else {
11172                 if (err)
11173                         raise_error_syntax("bad fd number");
11174                 n->ndup.vname = makename();
11175         }
11176 }
11177
11178 /*
11179  * Returns true if the text contains nothing to expand (no dollar signs
11180  * or backquotes).
11181  */
11182 static int
11183 noexpand(const char *text)
11184 {
11185         unsigned char c;
11186
11187         while ((c = *text++) != '\0') {
11188                 if (c == CTLQUOTEMARK)
11189                         continue;
11190                 if (c == CTLESC)
11191                         text++;
11192                 else if (SIT(c, BASESYNTAX) == CCTL)
11193                         return 0;
11194         }
11195         return 1;
11196 }
11197
11198 static void
11199 parsefname(void)
11200 {
11201         union node *n = redirnode;
11202
11203         if (readtoken() != TWORD)
11204                 raise_error_unexpected_syntax(-1);
11205         if (n->type == NHERE) {
11206                 struct heredoc *here = heredoc;
11207                 struct heredoc *p;
11208                 int i;
11209
11210                 if (quoteflag == 0)
11211                         n->type = NXHERE;
11212                 TRACE(("Here document %d\n", n->type));
11213                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11214                         raise_error_syntax("illegal eof marker for << redirection");
11215                 rmescapes(wordtext, 0);
11216                 here->eofmark = wordtext;
11217                 here->next = NULL;
11218                 if (heredoclist == NULL)
11219                         heredoclist = here;
11220                 else {
11221                         for (p = heredoclist; p->next; p = p->next)
11222                                 continue;
11223                         p->next = here;
11224                 }
11225         } else if (n->type == NTOFD || n->type == NFROMFD) {
11226                 fixredir(n, wordtext, 0);
11227         } else {
11228                 n->nfile.fname = makename();
11229         }
11230 }
11231
11232 static union node *
11233 simplecmd(void)
11234 {
11235         union node *args, **app;
11236         union node *n = NULL;
11237         union node *vars, **vpp;
11238         union node **rpp, *redir;
11239         int savecheckkwd;
11240 #if BASH_TEST2
11241         smallint double_brackets_flag = 0;
11242 #endif
11243         IF_BASH_FUNCTION(smallint function_flag = 0;)
11244
11245         args = NULL;
11246         app = &args;
11247         vars = NULL;
11248         vpp = &vars;
11249         redir = NULL;
11250         rpp = &redir;
11251
11252         savecheckkwd = CHKALIAS;
11253         for (;;) {
11254                 int t;
11255                 checkkwd = savecheckkwd;
11256                 t = readtoken();
11257                 switch (t) {
11258 #if BASH_FUNCTION
11259                 case TFUNCTION:
11260                         if (peektoken() != TWORD)
11261                                 raise_error_unexpected_syntax(TWORD);
11262                         function_flag = 1;
11263                         break;
11264 #endif
11265 #if BASH_TEST2
11266                 case TAND: /* "&&" */
11267                 case TOR: /* "||" */
11268                         if (!double_brackets_flag) {
11269                                 tokpushback = 1;
11270                                 goto out;
11271                         }
11272                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11273 #endif
11274                 case TWORD:
11275                         n = stzalloc(sizeof(struct narg));
11276                         n->type = NARG;
11277                         /*n->narg.next = NULL; - stzalloc did it */
11278                         n->narg.text = wordtext;
11279 #if BASH_TEST2
11280                         if (strcmp("[[", wordtext) == 0)
11281                                 double_brackets_flag = 1;
11282                         else if (strcmp("]]", wordtext) == 0)
11283                                 double_brackets_flag = 0;
11284 #endif
11285                         n->narg.backquote = backquotelist;
11286                         if (savecheckkwd && isassignment(wordtext)) {
11287                                 *vpp = n;
11288                                 vpp = &n->narg.next;
11289                         } else {
11290                                 *app = n;
11291                                 app = &n->narg.next;
11292                                 savecheckkwd = 0;
11293                         }
11294 #if BASH_FUNCTION
11295                         if (function_flag) {
11296                                 checkkwd = CHKNL | CHKKWD;
11297                                 switch (peektoken()) {
11298                                 case TBEGIN:
11299                                 case TIF:
11300                                 case TCASE:
11301                                 case TUNTIL:
11302                                 case TWHILE:
11303                                 case TFOR:
11304                                         goto do_func;
11305                                 case TLP:
11306                                         function_flag = 0;
11307                                         break;
11308                                 case TWORD:
11309                                         if (strcmp("[[", wordtext) == 0)
11310                                                 goto do_func;
11311                                         /* fall through */
11312                                 default:
11313                                         raise_error_unexpected_syntax(-1);
11314                                 }
11315                         }
11316 #endif
11317                         break;
11318                 case TREDIR:
11319                         *rpp = n = redirnode;
11320                         rpp = &n->nfile.next;
11321                         parsefname();   /* read name of redirection file */
11322                         break;
11323                 case TLP:
11324  IF_BASH_FUNCTION(do_func:)
11325                         if (args && app == &args->narg.next
11326                          && !vars && !redir
11327                         ) {
11328                                 struct builtincmd *bcmd;
11329                                 const char *name;
11330
11331                                 /* We have a function */
11332                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11333                                         raise_error_unexpected_syntax(TRP);
11334                                 name = n->narg.text;
11335                                 if (!goodname(name)
11336                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11337                                 ) {
11338                                         raise_error_syntax("bad function name");
11339                                 }
11340                                 n->type = NDEFUN;
11341                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11342                                 n->narg.next = parse_command();
11343                                 return n;
11344                         }
11345                         IF_BASH_FUNCTION(function_flag = 0;)
11346                         /* fall through */
11347                 default:
11348                         tokpushback = 1;
11349                         goto out;
11350                 }
11351         }
11352  out:
11353         *app = NULL;
11354         *vpp = NULL;
11355         *rpp = NULL;
11356         n = stzalloc(sizeof(struct ncmd));
11357         n->type = NCMD;
11358         n->ncmd.args = args;
11359         n->ncmd.assign = vars;
11360         n->ncmd.redirect = redir;
11361         return n;
11362 }
11363
11364 static union node *
11365 parse_command(void)
11366 {
11367         union node *n1, *n2;
11368         union node *ap, **app;
11369         union node *cp, **cpp;
11370         union node *redir, **rpp;
11371         union node **rpp2;
11372         int t;
11373
11374         redir = NULL;
11375         rpp2 = &redir;
11376
11377         switch (readtoken()) {
11378         default:
11379                 raise_error_unexpected_syntax(-1);
11380                 /* NOTREACHED */
11381         case TIF:
11382                 n1 = stzalloc(sizeof(struct nif));
11383                 n1->type = NIF;
11384                 n1->nif.test = list(0);
11385                 if (readtoken() != TTHEN)
11386                         raise_error_unexpected_syntax(TTHEN);
11387                 n1->nif.ifpart = list(0);
11388                 n2 = n1;
11389                 while (readtoken() == TELIF) {
11390                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11391                         n2 = n2->nif.elsepart;
11392                         n2->type = NIF;
11393                         n2->nif.test = list(0);
11394                         if (readtoken() != TTHEN)
11395                                 raise_error_unexpected_syntax(TTHEN);
11396                         n2->nif.ifpart = list(0);
11397                 }
11398                 if (lasttoken == TELSE)
11399                         n2->nif.elsepart = list(0);
11400                 else {
11401                         n2->nif.elsepart = NULL;
11402                         tokpushback = 1;
11403                 }
11404                 t = TFI;
11405                 break;
11406         case TWHILE:
11407         case TUNTIL: {
11408                 int got;
11409                 n1 = stzalloc(sizeof(struct nbinary));
11410                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11411                 n1->nbinary.ch1 = list(0);
11412                 got = readtoken();
11413                 if (got != TDO) {
11414                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11415                                         got == TWORD ? wordtext : ""));
11416                         raise_error_unexpected_syntax(TDO);
11417                 }
11418                 n1->nbinary.ch2 = list(0);
11419                 t = TDONE;
11420                 break;
11421         }
11422         case TFOR:
11423                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11424                         raise_error_syntax("bad for loop variable");
11425                 n1 = stzalloc(sizeof(struct nfor));
11426                 n1->type = NFOR;
11427                 n1->nfor.var = wordtext;
11428                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11429                 if (readtoken() == TIN) {
11430                         app = &ap;
11431                         while (readtoken() == TWORD) {
11432                                 n2 = stzalloc(sizeof(struct narg));
11433                                 n2->type = NARG;
11434                                 /*n2->narg.next = NULL; - stzalloc did it */
11435                                 n2->narg.text = wordtext;
11436                                 n2->narg.backquote = backquotelist;
11437                                 *app = n2;
11438                                 app = &n2->narg.next;
11439                         }
11440                         *app = NULL;
11441                         n1->nfor.args = ap;
11442                         if (lasttoken != TNL && lasttoken != TSEMI)
11443                                 raise_error_unexpected_syntax(-1);
11444                 } else {
11445                         n2 = stzalloc(sizeof(struct narg));
11446                         n2->type = NARG;
11447                         /*n2->narg.next = NULL; - stzalloc did it */
11448                         n2->narg.text = (char *)dolatstr;
11449                         /*n2->narg.backquote = NULL;*/
11450                         n1->nfor.args = n2;
11451                         /*
11452                          * Newline or semicolon here is optional (but note
11453                          * that the original Bourne shell only allowed NL).
11454                          */
11455                         if (lasttoken != TSEMI)
11456                                 tokpushback = 1;
11457                 }
11458                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11459                 if (readtoken() != TDO)
11460                         raise_error_unexpected_syntax(TDO);
11461                 n1->nfor.body = list(0);
11462                 t = TDONE;
11463                 break;
11464         case TCASE:
11465                 n1 = stzalloc(sizeof(struct ncase));
11466                 n1->type = NCASE;
11467                 if (readtoken() != TWORD)
11468                         raise_error_unexpected_syntax(TWORD);
11469                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11470                 n2->type = NARG;
11471                 /*n2->narg.next = NULL; - stzalloc did it */
11472                 n2->narg.text = wordtext;
11473                 n2->narg.backquote = backquotelist;
11474                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11475                 if (readtoken() != TIN)
11476                         raise_error_unexpected_syntax(TIN);
11477                 cpp = &n1->ncase.cases;
11478  next_case:
11479                 checkkwd = CHKNL | CHKKWD;
11480                 t = readtoken();
11481                 while (t != TESAC) {
11482                         if (lasttoken == TLP)
11483                                 readtoken();
11484                         *cpp = cp = stzalloc(sizeof(struct nclist));
11485                         cp->type = NCLIST;
11486                         app = &cp->nclist.pattern;
11487                         for (;;) {
11488                                 *app = ap = stzalloc(sizeof(struct narg));
11489                                 ap->type = NARG;
11490                                 /*ap->narg.next = NULL; - stzalloc did it */
11491                                 ap->narg.text = wordtext;
11492                                 ap->narg.backquote = backquotelist;
11493                                 if (readtoken() != TPIPE)
11494                                         break;
11495                                 app = &ap->narg.next;
11496                                 readtoken();
11497                         }
11498                         //ap->narg.next = NULL;
11499                         if (lasttoken != TRP)
11500                                 raise_error_unexpected_syntax(TRP);
11501                         cp->nclist.body = list(2);
11502
11503                         cpp = &cp->nclist.next;
11504
11505                         checkkwd = CHKNL | CHKKWD;
11506                         t = readtoken();
11507                         if (t != TESAC) {
11508                                 if (t != TENDCASE)
11509                                         raise_error_unexpected_syntax(TENDCASE);
11510                                 goto next_case;
11511                         }
11512                 }
11513                 *cpp = NULL;
11514                 goto redir;
11515         case TLP:
11516                 n1 = stzalloc(sizeof(struct nredir));
11517                 n1->type = NSUBSHELL;
11518                 n1->nredir.n = list(0);
11519                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11520                 t = TRP;
11521                 break;
11522         case TBEGIN:
11523                 n1 = list(0);
11524                 t = TEND;
11525                 break;
11526         IF_BASH_FUNCTION(case TFUNCTION:)
11527         case TWORD:
11528         case TREDIR:
11529                 tokpushback = 1;
11530                 return simplecmd();
11531         }
11532
11533         if (readtoken() != t)
11534                 raise_error_unexpected_syntax(t);
11535
11536  redir:
11537         /* Now check for redirection which may follow command */
11538         checkkwd = CHKKWD | CHKALIAS;
11539         rpp = rpp2;
11540         while (readtoken() == TREDIR) {
11541                 *rpp = n2 = redirnode;
11542                 rpp = &n2->nfile.next;
11543                 parsefname();
11544         }
11545         tokpushback = 1;
11546         *rpp = NULL;
11547         if (redir) {
11548                 if (n1->type != NSUBSHELL) {
11549                         n2 = stzalloc(sizeof(struct nredir));
11550                         n2->type = NREDIR;
11551                         n2->nredir.n = n1;
11552                         n1 = n2;
11553                 }
11554                 n1->nredir.redirect = redir;
11555         }
11556         return n1;
11557 }
11558
11559 #if BASH_DOLLAR_SQUOTE
11560 static int
11561 decode_dollar_squote(void)
11562 {
11563         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11564         int c, cnt;
11565         char *p;
11566         char buf[4];
11567
11568         c = pgetc();
11569         p = strchr(C_escapes, c);
11570         if (p) {
11571                 buf[0] = c;
11572                 p = buf;
11573                 cnt = 3;
11574                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11575                         do {
11576                                 c = pgetc();
11577                                 *++p = c;
11578                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11579                         pungetc();
11580                 } else if (c == 'x') { /* \xHH */
11581                         do {
11582                                 c = pgetc();
11583                                 *++p = c;
11584                         } while (isxdigit(c) && --cnt);
11585                         pungetc();
11586                         if (cnt == 3) { /* \x but next char is "bad" */
11587                                 c = 'x';
11588                                 goto unrecognized;
11589                         }
11590                 } else { /* simple seq like \\ or \t */
11591                         p++;
11592                 }
11593                 *p = '\0';
11594                 p = buf;
11595                 c = bb_process_escape_sequence((void*)&p);
11596         } else { /* unrecognized "\z": print both chars unless ' or " */
11597                 if (c != '\'' && c != '"') {
11598  unrecognized:
11599                         c |= 0x100; /* "please encode \, then me" */
11600                 }
11601         }
11602         return c;
11603 }
11604 #endif
11605
11606 /*
11607  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11608  * is not NULL, read a here document.  In the latter case, eofmark is the
11609  * word which marks the end of the document and striptabs is true if
11610  * leading tabs should be stripped from the document.  The argument c
11611  * is the first character of the input token or document.
11612  *
11613  * Because C does not have internal subroutines, I have simulated them
11614  * using goto's to implement the subroutine linkage.  The following macros
11615  * will run code that appears at the end of readtoken1.
11616  */
11617 #define CHECKEND()      {goto checkend; checkend_return:;}
11618 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11619 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11620 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11621 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11622 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11623 static int
11624 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11625 {
11626         /* NB: syntax parameter fits into smallint */
11627         /* c parameter is an unsigned char or PEOF or PEOA */
11628         char *out;
11629         size_t len;
11630         char line[EOFMARKLEN + 1];
11631         struct nodelist *bqlist;
11632         smallint quotef;
11633         smallint dblquote;
11634         smallint oldstyle;
11635         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11636         smallint pssyntax;   /* we are expanding a prompt string */
11637         int varnest;         /* levels of variables expansion */
11638         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11639         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11640         int dqvarnest;       /* levels of variables expansion within double quotes */
11641
11642         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11643
11644         startlinno = g_parsefile->linno;
11645         bqlist = NULL;
11646         quotef = 0;
11647         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11648         pssyntax = (syntax == PSSYNTAX);
11649         if (pssyntax)
11650                 syntax = DQSYNTAX;
11651         dblquote = (syntax == DQSYNTAX);
11652         varnest = 0;
11653         IF_FEATURE_SH_MATH(arinest = 0;)
11654         IF_FEATURE_SH_MATH(parenlevel = 0;)
11655         dqvarnest = 0;
11656
11657         STARTSTACKSTR(out);
11658  loop:
11659         /* For each line, until end of word */
11660         CHECKEND();     /* set c to PEOF if at end of here document */
11661         for (;;) {      /* until end of line or end of word */
11662                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11663                 switch (SIT(c, syntax)) {
11664                 case CNL:       /* '\n' */
11665                         if (syntax == BASESYNTAX)
11666                                 goto endword;   /* exit outer loop */
11667                         USTPUTC(c, out);
11668                         nlprompt();
11669                         c = pgetc();
11670                         goto loop;              /* continue outer loop */
11671                 case CWORD:
11672                         USTPUTC(c, out);
11673                         break;
11674                 case CCTL:
11675 #if BASH_DOLLAR_SQUOTE
11676                         if (c == '\\' && bash_dollar_squote) {
11677                                 c = decode_dollar_squote();
11678                                 if (c == '\0') {
11679                                         /* skip $'\000', $'\x00' (like bash) */
11680                                         break;
11681                                 }
11682                                 if (c & 0x100) {
11683                                         /* Unknown escape. Encode as '\z' */
11684                                         c = (unsigned char)c;
11685                                         if (eofmark == NULL || dblquote)
11686                                                 USTPUTC(CTLESC, out);
11687                                         USTPUTC('\\', out);
11688                                 }
11689                         }
11690 #endif
11691                         if (eofmark == NULL || dblquote)
11692                                 USTPUTC(CTLESC, out);
11693                         USTPUTC(c, out);
11694                         break;
11695                 case CBACK:     /* backslash */
11696                         c = pgetc_without_PEOA();
11697                         if (c == PEOF) {
11698                                 USTPUTC(CTLESC, out);
11699                                 USTPUTC('\\', out);
11700                                 pungetc();
11701                         } else if (c == '\n') {
11702                                 nlprompt();
11703                         } else {
11704                                 if (c == '$' && pssyntax) {
11705                                         USTPUTC(CTLESC, out);
11706                                         USTPUTC('\\', out);
11707                                 }
11708                                 /* Backslash is retained if we are in "str" and next char isn't special */
11709                                 if (dblquote
11710                                  && c != '\\'
11711                                  && c != '`'
11712                                  && c != '$'
11713                                  && (c != '"' || eofmark != NULL)
11714                                 ) {
11715                                         USTPUTC('\\', out);
11716                                 }
11717                                 USTPUTC(CTLESC, out);
11718                                 USTPUTC(c, out);
11719                                 quotef = 1;
11720                         }
11721                         break;
11722                 case CSQUOTE:
11723                         syntax = SQSYNTAX;
11724  quotemark:
11725                         if (eofmark == NULL) {
11726                                 USTPUTC(CTLQUOTEMARK, out);
11727                         }
11728                         break;
11729                 case CDQUOTE:
11730                         syntax = DQSYNTAX;
11731                         dblquote = 1;
11732                         goto quotemark;
11733                 case CENDQUOTE:
11734                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11735                         if (eofmark != NULL && varnest == 0) {
11736                                 USTPUTC(c, out);
11737                         } else {
11738                                 if (dqvarnest == 0) {
11739                                         syntax = BASESYNTAX;
11740                                         dblquote = 0;
11741                                 }
11742                                 quotef = 1;
11743                                 goto quotemark;
11744                         }
11745                         break;
11746                 case CVAR:      /* '$' */
11747                         PARSESUB();             /* parse substitution */
11748                         break;
11749                 case CENDVAR:   /* '}' */
11750                         if (varnest > 0) {
11751                                 varnest--;
11752                                 if (dqvarnest > 0) {
11753                                         dqvarnest--;
11754                                 }
11755                                 c = CTLENDVAR;
11756                         }
11757                         USTPUTC(c, out);
11758                         break;
11759 #if ENABLE_FEATURE_SH_MATH
11760                 case CLP:       /* '(' in arithmetic */
11761                         parenlevel++;
11762                         USTPUTC(c, out);
11763                         break;
11764                 case CRP:       /* ')' in arithmetic */
11765                         if (parenlevel > 0) {
11766                                 parenlevel--;
11767                         } else {
11768                                 if (pgetc_eatbnl() == ')') {
11769                                         c = CTLENDARI;
11770                                         if (--arinest == 0) {
11771                                                 syntax = prevsyntax;
11772                                         }
11773                                 } else {
11774                                         /*
11775                                          * unbalanced parens
11776                                          * (don't 2nd guess - no error)
11777                                          */
11778                                         pungetc();
11779                                 }
11780                         }
11781                         USTPUTC(c, out);
11782                         break;
11783 #endif
11784                 case CBQUOTE:   /* '`' */
11785                         PARSEBACKQOLD();
11786                         break;
11787                 case CENDFILE:
11788                         goto endword;           /* exit outer loop */
11789                 case CIGN:
11790                         break;
11791                 default:
11792                         if (varnest == 0) {
11793 #if BASH_REDIR_OUTPUT
11794                                 if (c == '&') {
11795 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11796                                         if (pgetc() == '>')
11797                                                 c = 0x100 + '>'; /* flag &> */
11798                                         pungetc();
11799                                 }
11800 #endif
11801                                 goto endword;   /* exit outer loop */
11802                         }
11803                         IF_ASH_ALIAS(if (c != PEOA))
11804                                 USTPUTC(c, out);
11805                 }
11806                 c = pgetc();
11807         } /* for (;;) */
11808  endword:
11809
11810 #if ENABLE_FEATURE_SH_MATH
11811         if (syntax == ARISYNTAX)
11812                 raise_error_syntax("missing '))'");
11813 #endif
11814         if (syntax != BASESYNTAX && eofmark == NULL)
11815                 raise_error_syntax("unterminated quoted string");
11816         if (varnest != 0) {
11817                 startlinno = g_parsefile->linno;
11818                 /* { */
11819                 raise_error_syntax("missing '}'");
11820         }
11821         USTPUTC('\0', out);
11822         len = out - (char *)stackblock();
11823         out = stackblock();
11824         if (eofmark == NULL) {
11825                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11826                  && quotef == 0
11827                 ) {
11828                         if (isdigit_str9(out)) {
11829                                 PARSEREDIR(); /* passed as params: out, c */
11830                                 lasttoken = TREDIR;
11831                                 return lasttoken;
11832                         }
11833                         /* else: non-number X seen, interpret it
11834                          * as "NNNX>file" = "NNNX >file" */
11835                 }
11836                 pungetc();
11837         }
11838         quoteflag = quotef;
11839         backquotelist = bqlist;
11840         grabstackblock(len);
11841         wordtext = out;
11842         lasttoken = TWORD;
11843         return lasttoken;
11844 /* end of readtoken routine */
11845
11846 /*
11847  * Check to see whether we are at the end of the here document.  When this
11848  * is called, c is set to the first character of the next input line.  If
11849  * we are at the end of the here document, this routine sets the c to PEOF.
11850  */
11851 checkend: {
11852         if (eofmark) {
11853 #if ENABLE_ASH_ALIAS
11854                 if (c == PEOA)
11855                         c = pgetc_without_PEOA();
11856 #endif
11857                 if (striptabs) {
11858                         while (c == '\t') {
11859                                 c = pgetc_without_PEOA();
11860                         }
11861                 }
11862                 if (c == *eofmark) {
11863                         if (pfgets(line, sizeof(line)) != NULL) {
11864                                 char *p, *q;
11865                                 int cc;
11866
11867                                 p = line;
11868                                 for (q = eofmark + 1;; p++, q++) {
11869                                         cc = *p;
11870                                         if (cc == '\n')
11871                                                 cc = 0;
11872                                         if (!*q || cc != *q)
11873                                                 break;
11874                                 }
11875                                 if (cc == *q) {
11876                                         c = PEOF;
11877                                         nlnoprompt();
11878                                 } else {
11879                                         pushstring(line, NULL);
11880                                 }
11881                         }
11882                 }
11883         }
11884         goto checkend_return;
11885 }
11886
11887 /*
11888  * Parse a redirection operator.  The variable "out" points to a string
11889  * specifying the fd to be redirected.  The variable "c" contains the
11890  * first character of the redirection operator.
11891  */
11892 parseredir: {
11893         /* out is already checked to be a valid number or "" */
11894         int fd = (*out == '\0' ? -1 : atoi(out));
11895         union node *np;
11896
11897         np = stzalloc(sizeof(struct nfile));
11898         if (c == '>') {
11899                 np->nfile.fd = 1;
11900                 c = pgetc();
11901                 if (c == '>')
11902                         np->type = NAPPEND;
11903                 else if (c == '|')
11904                         np->type = NCLOBBER;
11905                 else if (c == '&')
11906                         np->type = NTOFD;
11907                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11908                 else {
11909                         np->type = NTO;
11910                         pungetc();
11911                 }
11912         }
11913 #if BASH_REDIR_OUTPUT
11914         else if (c == 0x100 + '>') { /* this flags &> redirection */
11915                 np->nfile.fd = 1;
11916                 pgetc(); /* this is '>', no need to check */
11917                 np->type = NTO2;
11918         }
11919 #endif
11920         else { /* c == '<' */
11921                 /*np->nfile.fd = 0; - stzalloc did it */
11922                 c = pgetc();
11923                 switch (c) {
11924                 case '<':
11925                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11926                                 np = stzalloc(sizeof(struct nhere));
11927                                 /*np->nfile.fd = 0; - stzalloc did it */
11928                         }
11929                         np->type = NHERE;
11930                         heredoc = stzalloc(sizeof(struct heredoc));
11931                         heredoc->here = np;
11932                         c = pgetc();
11933                         if (c == '-') {
11934                                 heredoc->striptabs = 1;
11935                         } else {
11936                                 /*heredoc->striptabs = 0; - stzalloc did it */
11937                                 pungetc();
11938                         }
11939                         break;
11940
11941                 case '&':
11942                         np->type = NFROMFD;
11943                         break;
11944
11945                 case '>':
11946                         np->type = NFROMTO;
11947                         break;
11948
11949                 default:
11950                         np->type = NFROM;
11951                         pungetc();
11952                         break;
11953                 }
11954         }
11955         if (fd >= 0)
11956                 np->nfile.fd = fd;
11957         redirnode = np;
11958         goto parseredir_return;
11959 }
11960
11961 /*
11962  * Parse a substitution.  At this point, we have read the dollar sign
11963  * and nothing else.
11964  */
11965
11966 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11967  * (assuming ascii char codes, as the original implementation did) */
11968 #define is_special(c) \
11969         (((unsigned)(c) - 33 < 32) \
11970                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11971 parsesub: {
11972         unsigned char subtype;
11973         int typeloc;
11974
11975         c = pgetc_eatbnl();
11976         if (c > 255 /* PEOA or PEOF */
11977          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11978         ) {
11979 #if BASH_DOLLAR_SQUOTE
11980                 if (syntax != DQSYNTAX && c == '\'')
11981                         bash_dollar_squote = 1;
11982                 else
11983 #endif
11984                         USTPUTC('$', out);
11985                 pungetc();
11986         } else if (c == '(') {
11987                 /* $(command) or $((arith)) */
11988                 if (pgetc_eatbnl() == '(') {
11989 #if ENABLE_FEATURE_SH_MATH
11990                         PARSEARITH();
11991 #else
11992                         raise_error_syntax("support for $((arith)) is disabled");
11993 #endif
11994                 } else {
11995                         pungetc();
11996                         PARSEBACKQNEW();
11997                 }
11998         } else {
11999                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12000                 USTPUTC(CTLVAR, out);
12001                 typeloc = out - (char *)stackblock();
12002                 STADJUST(1, out);
12003                 subtype = VSNORMAL;
12004                 if (c == '{') {
12005                         c = pgetc_eatbnl();
12006                         subtype = 0;
12007                 }
12008  varname:
12009                 if (is_name(c)) {
12010                         /* $[{[#]]NAME[}] */
12011                         do {
12012                                 STPUTC(c, out);
12013                                 c = pgetc_eatbnl();
12014                         } while (is_in_name(c));
12015                 } else if (isdigit(c)) {
12016                         /* $[{[#]]NUM[}] */
12017                         do {
12018                                 STPUTC(c, out);
12019                                 c = pgetc_eatbnl();
12020                         } while (isdigit(c));
12021                 } else if (is_special(c)) {
12022                         /* $[{[#]]<specialchar>[}] */
12023                         int cc = c;
12024
12025                         c = pgetc_eatbnl();
12026                         if (!subtype && cc == '#') {
12027                                 subtype = VSLENGTH;
12028                                 if (c == '_' || isalnum(c))
12029                                         goto varname;
12030                                 cc = c;
12031                                 c = pgetc_eatbnl();
12032                                 if (cc == '}' || c != '}') {
12033                                         pungetc();
12034                                         subtype = 0;
12035                                         c = cc;
12036                                         cc = '#';
12037                                 }
12038                         }
12039                         USTPUTC(cc, out);
12040                 } else {
12041                         goto badsub;
12042                 }
12043                 if (c != '}' && subtype == VSLENGTH) {
12044                         /* ${#VAR didn't end with } */
12045                         goto badsub;
12046                 }
12047
12048                 if (subtype == 0) {
12049                         static const char types[] ALIGN1 = "}-+?=";
12050                         /* ${VAR...} but not $VAR or ${#VAR} */
12051                         /* c == first char after VAR */
12052                         switch (c) {
12053                         case ':':
12054                                 c = pgetc_eatbnl();
12055 #if BASH_SUBSTR
12056                                 /* This check is only needed to not misinterpret
12057                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12058                                  * constructs.
12059                                  */
12060                                 if (!strchr(types, c)) {
12061                                         subtype = VSSUBSTR;
12062                                         pungetc();
12063                                         break; /* "goto badsub" is bigger (!) */
12064                                 }
12065 #endif
12066                                 subtype = VSNUL;
12067                                 /*FALLTHROUGH*/
12068                         default: {
12069                                 const char *p = strchr(types, c);
12070                                 if (p == NULL)
12071                                         break;
12072                                 subtype |= p - types + VSNORMAL;
12073                                 break;
12074                         }
12075                         case '%':
12076                         case '#': {
12077                                 int cc = c;
12078                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12079                                 c = pgetc_eatbnl();
12080                                 if (c != cc)
12081                                         goto badsub;
12082                                 subtype++;
12083                                 break;
12084                         }
12085 #if BASH_PATTERN_SUBST
12086                         case '/':
12087                                 /* ${v/[/]pattern/repl} */
12088 //TODO: encode pattern and repl separately.
12089 // Currently ${v/$var_with_slash/repl} is horribly broken
12090                                 subtype = VSREPLACE;
12091                                 c = pgetc_eatbnl();
12092                                 if (c != '/')
12093                                         goto badsub;
12094                                 subtype++; /* VSREPLACEALL */
12095                                 break;
12096 #endif
12097                         }
12098                 } else {
12099  badsub:
12100                         pungetc();
12101                 }
12102                 ((unsigned char *)stackblock())[typeloc] = subtype;
12103                 if (subtype != VSNORMAL) {
12104                         varnest++;
12105                         if (dblquote)
12106                                 dqvarnest++;
12107                 }
12108                 STPUTC('=', out);
12109         }
12110         goto parsesub_return;
12111 }
12112
12113 /*
12114  * Called to parse command substitutions.  Newstyle is set if the command
12115  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12116  * list of commands (passed by reference), and savelen is the number of
12117  * characters on the top of the stack which must be preserved.
12118  */
12119 parsebackq: {
12120         struct nodelist **nlpp;
12121         union node *n;
12122         char *str;
12123         size_t savelen;
12124         smallint saveprompt = 0;
12125
12126         str = NULL;
12127         savelen = out - (char *)stackblock();
12128         if (savelen > 0) {
12129                 /*
12130                  * FIXME: this can allocate very large block on stack and SEGV.
12131                  * Example:
12132                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12133                  * allocates 100kb for every command subst. With about
12134                  * a hundred command substitutions stack overflows.
12135                  * With larger prepended string, SEGV happens sooner.
12136                  */
12137                 str = alloca(savelen);
12138                 memcpy(str, stackblock(), savelen);
12139         }
12140
12141         if (oldstyle) {
12142                 /* We must read until the closing backquote, giving special
12143                  * treatment to some slashes, and then push the string and
12144                  * reread it as input, interpreting it normally.
12145                  */
12146                 char *pout;
12147                 size_t psavelen;
12148                 char *pstr;
12149
12150                 STARTSTACKSTR(pout);
12151                 for (;;) {
12152                         int pc;
12153
12154                         setprompt_if(needprompt, 2);
12155                         pc = pgetc();
12156                         switch (pc) {
12157                         case '`':
12158                                 goto done;
12159
12160                         case '\\':
12161                                 pc = pgetc();
12162                                 if (pc == '\n') {
12163                                         nlprompt();
12164                                         /*
12165                                          * If eating a newline, avoid putting
12166                                          * the newline into the new character
12167                                          * stream (via the STPUTC after the
12168                                          * switch).
12169                                          */
12170                                         continue;
12171                                 }
12172                                 if (pc != '\\' && pc != '`' && pc != '$'
12173                                  && (!dblquote || pc != '"')
12174                                 ) {
12175                                         STPUTC('\\', pout);
12176                                 }
12177                                 if (pc <= 255 /* not PEOA or PEOF */) {
12178                                         break;
12179                                 }
12180                                 /* fall through */
12181
12182                         case PEOF:
12183                         IF_ASH_ALIAS(case PEOA:)
12184                                 startlinno = g_parsefile->linno;
12185                                 raise_error_syntax("EOF in backquote substitution");
12186
12187                         case '\n':
12188                                 nlnoprompt();
12189                                 break;
12190
12191                         default:
12192                                 break;
12193                         }
12194                         STPUTC(pc, pout);
12195                 }
12196  done:
12197                 STPUTC('\0', pout);
12198                 psavelen = pout - (char *)stackblock();
12199                 if (psavelen > 0) {
12200                         pstr = grabstackstr(pout);
12201                         setinputstring(pstr);
12202                 }
12203         }
12204         nlpp = &bqlist;
12205         while (*nlpp)
12206                 nlpp = &(*nlpp)->next;
12207         *nlpp = stzalloc(sizeof(**nlpp));
12208         /* (*nlpp)->next = NULL; - stzalloc did it */
12209
12210         if (oldstyle) {
12211                 saveprompt = doprompt;
12212                 doprompt = 0;
12213         }
12214
12215         n = list(2);
12216
12217         if (oldstyle)
12218                 doprompt = saveprompt;
12219         else if (readtoken() != TRP)
12220                 raise_error_unexpected_syntax(TRP);
12221
12222         (*nlpp)->n = n;
12223         if (oldstyle) {
12224                 /*
12225                  * Start reading from old file again, ignoring any pushed back
12226                  * tokens left from the backquote parsing
12227                  */
12228                 popfile();
12229                 tokpushback = 0;
12230         }
12231         while (stackblocksize() <= savelen)
12232                 growstackblock();
12233         STARTSTACKSTR(out);
12234         if (str) {
12235                 memcpy(out, str, savelen);
12236                 STADJUST(savelen, out);
12237         }
12238         USTPUTC(CTLBACKQ, out);
12239         if (oldstyle)
12240                 goto parsebackq_oldreturn;
12241         goto parsebackq_newreturn;
12242 }
12243
12244 #if ENABLE_FEATURE_SH_MATH
12245 /*
12246  * Parse an arithmetic expansion (indicate start of one and set state)
12247  */
12248 parsearith: {
12249         if (++arinest == 1) {
12250                 prevsyntax = syntax;
12251                 syntax = ARISYNTAX;
12252         }
12253         USTPUTC(CTLARI, out);
12254         goto parsearith_return;
12255 }
12256 #endif
12257 } /* end of readtoken */
12258
12259 /*
12260  * Read the next input token.
12261  * If the token is a word, we set backquotelist to the list of cmds in
12262  *      backquotes.  We set quoteflag to true if any part of the word was
12263  *      quoted.
12264  * If the token is TREDIR, then we set redirnode to a structure containing
12265  *      the redirection.
12266  * In all cases, the variable startlinno is set to the number of the line
12267  *      on which the token starts.
12268  *
12269  * [Change comment:  here documents and internal procedures]
12270  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12271  *  word parsing code into a separate routine.  In this case, readtoken
12272  *  doesn't need to have any internal procedures, but parseword does.
12273  *  We could also make parseoperator in essence the main routine, and
12274  *  have parseword (readtoken1?) handle both words and redirection.]
12275  */
12276 #define NEW_xxreadtoken
12277 #ifdef NEW_xxreadtoken
12278 /* singles must be first! */
12279 static const char xxreadtoken_chars[7] ALIGN1 = {
12280         '\n', '(', ')', /* singles */
12281         '&', '|', ';',  /* doubles */
12282         0
12283 };
12284
12285 #define xxreadtoken_singles 3
12286 #define xxreadtoken_doubles 3
12287
12288 static const char xxreadtoken_tokens[] ALIGN1 = {
12289         TNL, TLP, TRP,          /* only single occurrence allowed */
12290         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12291         TEOF,                   /* corresponds to trailing nul */
12292         TAND, TOR, TENDCASE     /* if double occurrence */
12293 };
12294
12295 static int
12296 xxreadtoken(void)
12297 {
12298         int c;
12299
12300         if (tokpushback) {
12301                 tokpushback = 0;
12302                 return lasttoken;
12303         }
12304         setprompt_if(needprompt, 2);
12305         startlinno = g_parsefile->linno;
12306         for (;;) {                      /* until token or start of word found */
12307                 c = pgetc();
12308                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12309                         continue;
12310
12311                 if (c == '#') {
12312                         while ((c = pgetc()) != '\n' && c != PEOF)
12313                                 continue;
12314                         pungetc();
12315                 } else if (c == '\\') {
12316                         if (pgetc() != '\n') {
12317                                 pungetc();
12318                                 break; /* return readtoken1(...) */
12319                         }
12320                         nlprompt();
12321                 } else {
12322                         const char *p;
12323
12324                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12325                         if (c != PEOF) {
12326                                 if (c == '\n') {
12327                                         nlnoprompt();
12328                                 }
12329
12330                                 p = strchr(xxreadtoken_chars, c);
12331                                 if (p == NULL)
12332                                         break; /* return readtoken1(...) */
12333
12334                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12335                                         int cc = pgetc();
12336                                         if (cc == c) {    /* double occurrence? */
12337                                                 p += xxreadtoken_doubles + 1;
12338                                         } else {
12339                                                 pungetc();
12340 #if BASH_REDIR_OUTPUT
12341                                                 if (c == '&' && cc == '>') /* &> */
12342                                                         break; /* return readtoken1(...) */
12343 #endif
12344                                         }
12345                                 }
12346                         }
12347                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12348                         return lasttoken;
12349                 }
12350         } /* for (;;) */
12351
12352         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12353 }
12354 #else /* old xxreadtoken */
12355 #define RETURN(token)   return lasttoken = token
12356 static int
12357 xxreadtoken(void)
12358 {
12359         int c;
12360
12361         if (tokpushback) {
12362                 tokpushback = 0;
12363                 return lasttoken;
12364         }
12365         setprompt_if(needprompt, 2);
12366         startlinno = g_parsefile->linno;
12367         for (;;) {      /* until token or start of word found */
12368                 c = pgetc();
12369                 switch (c) {
12370                 case ' ': case '\t':
12371                 IF_ASH_ALIAS(case PEOA:)
12372                         continue;
12373                 case '#':
12374                         while ((c = pgetc()) != '\n' && c != PEOF)
12375                                 continue;
12376                         pungetc();
12377                         continue;
12378                 case '\\':
12379                         if (pgetc() == '\n') {
12380                                 nlprompt();
12381                                 continue;
12382                         }
12383                         pungetc();
12384                         goto breakloop;
12385                 case '\n':
12386                         nlnoprompt();
12387                         RETURN(TNL);
12388                 case PEOF:
12389                         RETURN(TEOF);
12390                 case '&':
12391                         if (pgetc() == '&')
12392                                 RETURN(TAND);
12393                         pungetc();
12394                         RETURN(TBACKGND);
12395                 case '|':
12396                         if (pgetc() == '|')
12397                                 RETURN(TOR);
12398                         pungetc();
12399                         RETURN(TPIPE);
12400                 case ';':
12401                         if (pgetc() == ';')
12402                                 RETURN(TENDCASE);
12403                         pungetc();
12404                         RETURN(TSEMI);
12405                 case '(':
12406                         RETURN(TLP);
12407                 case ')':
12408                         RETURN(TRP);
12409                 default:
12410                         goto breakloop;
12411                 }
12412         }
12413  breakloop:
12414         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12415 #undef RETURN
12416 }
12417 #endif /* old xxreadtoken */
12418
12419 static int
12420 readtoken(void)
12421 {
12422         int t;
12423         int kwd = checkkwd;
12424 #if DEBUG
12425         smallint alreadyseen = tokpushback;
12426 #endif
12427
12428 #if ENABLE_ASH_ALIAS
12429  top:
12430 #endif
12431
12432         t = xxreadtoken();
12433
12434         /*
12435          * eat newlines
12436          */
12437         if (kwd & CHKNL) {
12438                 while (t == TNL) {
12439                         parseheredoc();
12440                         t = xxreadtoken();
12441                 }
12442         }
12443
12444         if (t != TWORD || quoteflag) {
12445                 goto out;
12446         }
12447
12448         /*
12449          * check for keywords
12450          */
12451         if (kwd & CHKKWD) {
12452                 const char *const *pp;
12453
12454                 pp = findkwd(wordtext);
12455                 if (pp) {
12456                         lasttoken = t = pp - tokname_array;
12457                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12458                         goto out;
12459                 }
12460         }
12461
12462         if (checkkwd & CHKALIAS) {
12463 #if ENABLE_ASH_ALIAS
12464                 struct alias *ap;
12465                 ap = lookupalias(wordtext, 1);
12466                 if (ap != NULL) {
12467                         if (*ap->val) {
12468                                 pushstring(ap->val, ap);
12469                         }
12470                         goto top;
12471                 }
12472 #endif
12473         }
12474  out:
12475         checkkwd = 0;
12476 #if DEBUG
12477         if (!alreadyseen)
12478                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12479         else
12480                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12481 #endif
12482         return t;
12483 }
12484
12485 static int
12486 peektoken(void)
12487 {
12488         int t;
12489
12490         t = readtoken();
12491         tokpushback = 1;
12492         return t;
12493 }
12494
12495 /*
12496  * Read and parse a command.  Returns NODE_EOF on end of file.
12497  * (NULL is a valid parse tree indicating a blank line.)
12498  */
12499 static union node *
12500 parsecmd(int interact)
12501 {
12502         tokpushback = 0;
12503         checkkwd = 0;
12504         heredoclist = 0;
12505         doprompt = interact;
12506         setprompt_if(doprompt, doprompt);
12507         needprompt = 0;
12508         return list(1);
12509 }
12510
12511 /*
12512  * Input any here documents.
12513  */
12514 static void
12515 parseheredoc(void)
12516 {
12517         struct heredoc *here;
12518         union node *n;
12519
12520         here = heredoclist;
12521         heredoclist = NULL;
12522
12523         while (here) {
12524                 setprompt_if(needprompt, 2);
12525                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12526                                 here->eofmark, here->striptabs);
12527                 n = stzalloc(sizeof(struct narg));
12528                 n->narg.type = NARG;
12529                 /*n->narg.next = NULL; - stzalloc did it */
12530                 n->narg.text = wordtext;
12531                 n->narg.backquote = backquotelist;
12532                 here->here->nhere.doc = n;
12533                 here = here->next;
12534         }
12535 }
12536
12537
12538 /*
12539  * called by editline -- any expansions to the prompt should be added here.
12540  */
12541 static const char *
12542 expandstr(const char *ps)
12543 {
12544         union node n;
12545         int saveprompt;
12546
12547         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12548          * and token processing _can_ alter it (delete NULs etc). */
12549         setinputstring((char *)ps);
12550
12551         saveprompt = doprompt;
12552         doprompt = 0;
12553         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12554         doprompt = saveprompt;
12555
12556         popfile();
12557
12558         n.narg.type = NARG;
12559         n.narg.next = NULL;
12560         n.narg.text = wordtext;
12561         n.narg.backquote = backquotelist;
12562
12563         expandarg(&n, NULL, EXP_QUOTED);
12564         return stackblock();
12565 }
12566
12567 /*
12568  * Execute a command or commands contained in a string.
12569  */
12570 static int
12571 evalstring(char *s, int flags)
12572 {
12573         struct jmploc *volatile savehandler;
12574         struct jmploc jmploc;
12575         int ex;
12576
12577         union node *n;
12578         struct stackmark smark;
12579         int status;
12580
12581         s = sstrdup(s);
12582         setinputstring(s);
12583         setstackmark(&smark);
12584
12585         status = 0;
12586         /* On exception inside execution loop, we must popfile().
12587          * Try interactively:
12588          *      readonly a=a
12589          *      command eval "a=b"  # throws "is read only" error
12590          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12591          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12592          */
12593         savehandler = exception_handler;
12594         ex = setjmp(jmploc.loc);
12595         if (ex)
12596                 goto out;
12597         exception_handler = &jmploc;
12598
12599         while ((n = parsecmd(0)) != NODE_EOF) {
12600                 int i;
12601
12602                 i = evaltree(n, flags);
12603                 if (n)
12604                         status = i;
12605                 popstackmark(&smark);
12606                 if (evalskip)
12607                         break;
12608         }
12609  out:
12610         popstackmark(&smark);
12611         popfile();
12612         stunalloc(s);
12613
12614         exception_handler = savehandler;
12615         if (ex)
12616                 longjmp(exception_handler->loc, ex);
12617
12618         return status;
12619 }
12620
12621 /*
12622  * The eval command.
12623  */
12624 static int FAST_FUNC
12625 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12626 {
12627         char *p;
12628         char *concat;
12629
12630         if (argv[1]) {
12631                 p = argv[1];
12632                 argv += 2;
12633                 if (argv[0]) {
12634                         STARTSTACKSTR(concat);
12635                         for (;;) {
12636                                 concat = stack_putstr(p, concat);
12637                                 p = *argv++;
12638                                 if (p == NULL)
12639                                         break;
12640                                 STPUTC(' ', concat);
12641                         }
12642                         STPUTC('\0', concat);
12643                         p = grabstackstr(concat);
12644                 }
12645                 return evalstring(p, flags & EV_TESTED);
12646         }
12647         return 0;
12648 }
12649
12650 /*
12651  * Read and execute commands.
12652  * "Top" is nonzero for the top level command loop;
12653  * it turns on prompting if the shell is interactive.
12654  */
12655 static int
12656 cmdloop(int top)
12657 {
12658         union node *n;
12659         struct stackmark smark;
12660         int inter;
12661         int status = 0;
12662         int numeof = 0;
12663
12664         TRACE(("cmdloop(%d) called\n", top));
12665         for (;;) {
12666                 int skip;
12667
12668                 setstackmark(&smark);
12669 #if JOBS
12670                 if (doing_jobctl)
12671                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12672 #endif
12673                 inter = 0;
12674                 if (iflag && top) {
12675                         inter++;
12676                         chkmail();
12677                 }
12678                 n = parsecmd(inter);
12679 #if DEBUG
12680                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12681                         showtree(n);
12682 #endif
12683                 if (n == NODE_EOF) {
12684                         if (!top || numeof >= 50)
12685                                 break;
12686                         if (!stoppedjobs()) {
12687                                 if (!Iflag)
12688                                         break;
12689                                 out2str("\nUse \"exit\" to leave shell.\n");
12690                         }
12691                         numeof++;
12692                 } else if (nflag == 0) {
12693                         int i;
12694
12695                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12696                         job_warning >>= 1;
12697                         numeof = 0;
12698                         i = evaltree(n, 0);
12699                         if (n)
12700                                 status = i;
12701                 }
12702                 popstackmark(&smark);
12703                 skip = evalskip;
12704
12705                 if (skip) {
12706                         evalskip &= ~SKIPFUNC;
12707                         break;
12708                 }
12709         }
12710         return status;
12711 }
12712
12713 /*
12714  * Take commands from a file.  To be compatible we should do a path
12715  * search for the file, which is necessary to find sub-commands.
12716  */
12717 static char *
12718 find_dot_file(char *name)
12719 {
12720         char *fullname;
12721         const char *path = pathval();
12722         struct stat statb;
12723
12724         /* don't try this for absolute or relative paths */
12725         if (strchr(name, '/'))
12726                 return name;
12727
12728         while ((fullname = path_advance(&path, name)) != NULL) {
12729                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12730                         /*
12731                          * Don't bother freeing here, since it will
12732                          * be freed by the caller.
12733                          */
12734                         return fullname;
12735                 }
12736                 if (fullname != name)
12737                         stunalloc(fullname);
12738         }
12739
12740         /* not found in the PATH */
12741         ash_msg_and_raise_error("%s: not found", name);
12742         /* NOTREACHED */
12743 }
12744
12745 static int FAST_FUNC
12746 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12747 {
12748         /* "false; . empty_file; echo $?" should print 0, not 1: */
12749         int status = 0;
12750         char *fullname;
12751         char **argv;
12752         char *args_need_save;
12753         struct strlist *sp;
12754         volatile struct shparam saveparam;
12755
12756         for (sp = cmdenviron; sp; sp = sp->next)
12757                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12758
12759         nextopt(nullstr); /* handle possible "--" */
12760         argv = argptr;
12761
12762         if (!argv[0]) {
12763                 /* bash says: "bash: .: filename argument required" */
12764                 return 2; /* bash compat */
12765         }
12766
12767         /* This aborts if file isn't found, which is POSIXly correct.
12768          * bash returns exitcode 1 instead.
12769          */
12770         fullname = find_dot_file(argv[0]);
12771         argv++;
12772         args_need_save = argv[0];
12773         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12774                 int argc;
12775                 saveparam = shellparam;
12776                 shellparam.malloced = 0;
12777                 argc = 1;
12778                 while (argv[argc])
12779                         argc++;
12780                 shellparam.nparam = argc;
12781                 shellparam.p = argv;
12782         };
12783
12784         /* This aborts if file can't be opened, which is POSIXly correct.
12785          * bash returns exitcode 1 instead.
12786          */
12787         setinputfile(fullname, INPUT_PUSH_FILE);
12788         commandname = fullname;
12789         status = cmdloop(0);
12790         popfile();
12791
12792         if (args_need_save) {
12793                 freeparam(&shellparam);
12794                 shellparam = saveparam;
12795         };
12796
12797         return status;
12798 }
12799
12800 static int FAST_FUNC
12801 exitcmd(int argc UNUSED_PARAM, char **argv)
12802 {
12803         if (stoppedjobs())
12804                 return 0;
12805         if (argv[1])
12806                 exitstatus = number(argv[1]);
12807         raise_exception(EXEXIT);
12808         /* NOTREACHED */
12809 }
12810
12811 /*
12812  * Read a file containing shell functions.
12813  */
12814 static void
12815 readcmdfile(char *name)
12816 {
12817         setinputfile(name, INPUT_PUSH_FILE);
12818         cmdloop(0);
12819         popfile();
12820 }
12821
12822
12823 /* ============ find_command inplementation */
12824
12825 /*
12826  * Resolve a command name.  If you change this routine, you may have to
12827  * change the shellexec routine as well.
12828  */
12829 static void
12830 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12831 {
12832         struct tblentry *cmdp;
12833         int idx;
12834         int prev;
12835         char *fullname;
12836         struct stat statb;
12837         int e;
12838         int updatetbl;
12839         struct builtincmd *bcmd;
12840
12841         /* If name contains a slash, don't use PATH or hash table */
12842         if (strchr(name, '/') != NULL) {
12843                 entry->u.index = -1;
12844                 if (act & DO_ABS) {
12845                         while (stat(name, &statb) < 0) {
12846 #ifdef SYSV
12847                                 if (errno == EINTR)
12848                                         continue;
12849 #endif
12850                                 entry->cmdtype = CMDUNKNOWN;
12851                                 return;
12852                         }
12853                 }
12854                 entry->cmdtype = CMDNORMAL;
12855                 return;
12856         }
12857
12858 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12859
12860         updatetbl = (path == pathval());
12861         if (!updatetbl) {
12862                 act |= DO_ALTPATH;
12863                 if (strstr(path, "%builtin") != NULL)
12864                         act |= DO_ALTBLTIN;
12865         }
12866
12867         /* If name is in the table, check answer will be ok */
12868         cmdp = cmdlookup(name, 0);
12869         if (cmdp != NULL) {
12870                 int bit;
12871
12872                 switch (cmdp->cmdtype) {
12873                 default:
12874 #if DEBUG
12875                         abort();
12876 #endif
12877                 case CMDNORMAL:
12878                         bit = DO_ALTPATH;
12879                         break;
12880                 case CMDFUNCTION:
12881                         bit = DO_NOFUNC;
12882                         break;
12883                 case CMDBUILTIN:
12884                         bit = DO_ALTBLTIN;
12885                         break;
12886                 }
12887                 if (act & bit) {
12888                         updatetbl = 0;
12889                         cmdp = NULL;
12890                 } else if (cmdp->rehash == 0)
12891                         /* if not invalidated by cd, we're done */
12892                         goto success;
12893         }
12894
12895         /* If %builtin not in path, check for builtin next */
12896         bcmd = find_builtin(name);
12897         if (bcmd) {
12898                 if (IS_BUILTIN_REGULAR(bcmd))
12899                         goto builtin_success;
12900                 if (act & DO_ALTPATH) {
12901                         if (!(act & DO_ALTBLTIN))
12902                                 goto builtin_success;
12903                 } else if (builtinloc <= 0) {
12904                         goto builtin_success;
12905                 }
12906         }
12907
12908 #if ENABLE_FEATURE_SH_STANDALONE
12909         {
12910                 int applet_no = find_applet_by_name(name);
12911                 if (applet_no >= 0) {
12912                         entry->cmdtype = CMDNORMAL;
12913                         entry->u.index = -2 - applet_no;
12914                         return;
12915                 }
12916         }
12917 #endif
12918
12919         /* We have to search path. */
12920         prev = -1;              /* where to start */
12921         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12922                 if (cmdp->cmdtype == CMDBUILTIN)
12923                         prev = builtinloc;
12924                 else
12925                         prev = cmdp->param.index;
12926         }
12927
12928         e = ENOENT;
12929         idx = -1;
12930  loop:
12931         while ((fullname = path_advance(&path, name)) != NULL) {
12932                 stunalloc(fullname);
12933                 /* NB: code below will still use fullname
12934                  * despite it being "unallocated" */
12935                 idx++;
12936                 if (pathopt) {
12937                         if (prefix(pathopt, "builtin")) {
12938                                 if (bcmd)
12939                                         goto builtin_success;
12940                                 continue;
12941                         }
12942                         if ((act & DO_NOFUNC)
12943                          || !prefix(pathopt, "func")
12944                         ) {     /* ignore unimplemented options */
12945                                 continue;
12946                         }
12947                 }
12948                 /* if rehash, don't redo absolute path names */
12949                 if (fullname[0] == '/' && idx <= prev) {
12950                         if (idx < prev)
12951                                 continue;
12952                         TRACE(("searchexec \"%s\": no change\n", name));
12953                         goto success;
12954                 }
12955                 while (stat(fullname, &statb) < 0) {
12956 #ifdef SYSV
12957                         if (errno == EINTR)
12958                                 continue;
12959 #endif
12960                         if (errno != ENOENT && errno != ENOTDIR)
12961                                 e = errno;
12962                         goto loop;
12963                 }
12964                 e = EACCES;     /* if we fail, this will be the error */
12965                 if (!S_ISREG(statb.st_mode))
12966                         continue;
12967                 if (pathopt) {          /* this is a %func directory */
12968                         stalloc(strlen(fullname) + 1);
12969                         /* NB: stalloc will return space pointed by fullname
12970                          * (because we don't have any intervening allocations
12971                          * between stunalloc above and this stalloc) */
12972                         readcmdfile(fullname);
12973                         cmdp = cmdlookup(name, 0);
12974                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12975                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12976                         stunalloc(fullname);
12977                         goto success;
12978                 }
12979                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12980                 if (!updatetbl) {
12981                         entry->cmdtype = CMDNORMAL;
12982                         entry->u.index = idx;
12983                         return;
12984                 }
12985                 INT_OFF;
12986                 cmdp = cmdlookup(name, 1);
12987                 cmdp->cmdtype = CMDNORMAL;
12988                 cmdp->param.index = idx;
12989                 INT_ON;
12990                 goto success;
12991         }
12992
12993         /* We failed.  If there was an entry for this command, delete it */
12994         if (cmdp && updatetbl)
12995                 delete_cmd_entry();
12996         if (act & DO_ERR)
12997                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12998         entry->cmdtype = CMDUNKNOWN;
12999         return;
13000
13001  builtin_success:
13002         if (!updatetbl) {
13003                 entry->cmdtype = CMDBUILTIN;
13004                 entry->u.cmd = bcmd;
13005                 return;
13006         }
13007         INT_OFF;
13008         cmdp = cmdlookup(name, 1);
13009         cmdp->cmdtype = CMDBUILTIN;
13010         cmdp->param.cmd = bcmd;
13011         INT_ON;
13012  success:
13013         cmdp->rehash = 0;
13014         entry->cmdtype = cmdp->cmdtype;
13015         entry->u = cmdp->param;
13016 }
13017
13018
13019 /*
13020  * The trap builtin.
13021  */
13022 static int FAST_FUNC
13023 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13024 {
13025         char *action;
13026         char **ap;
13027         int signo, exitcode;
13028
13029         nextopt(nullstr);
13030         ap = argptr;
13031         if (!*ap) {
13032                 for (signo = 0; signo < NSIG; signo++) {
13033                         char *tr = trap_ptr[signo];
13034                         if (tr) {
13035                                 /* note: bash adds "SIG", but only if invoked
13036                                  * as "bash". If called as "sh", or if set -o posix,
13037                                  * then it prints short signal names.
13038                                  * We are printing short names: */
13039                                 out1fmt("trap -- %s %s\n",
13040                                                 single_quote(tr),
13041                                                 get_signame(signo));
13042                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13043                  * In this case, we will exit very soon, no need to free(). */
13044                                 /* if (trap_ptr != trap && tp[0]) */
13045                                 /*      free(tr); */
13046                         }
13047                 }
13048                 /*
13049                 if (trap_ptr != trap) {
13050                         free(trap_ptr);
13051                         trap_ptr = trap;
13052                 }
13053                 */
13054                 return 0;
13055         }
13056
13057         action = NULL;
13058         if (ap[1])
13059                 action = *ap++;
13060         exitcode = 0;
13061         while (*ap) {
13062                 signo = get_signum(*ap);
13063                 if (signo < 0 || signo >= NSIG) {
13064                         /* Mimic bash message exactly */
13065                         ash_msg("%s: invalid signal specification", *ap);
13066                         exitcode = 1;
13067                         goto next;
13068                 }
13069                 INT_OFF;
13070                 if (action) {
13071                         if (LONE_DASH(action))
13072                                 action = NULL;
13073                         else {
13074                                 if (action[0]) /* not NULL and not "" and not "-" */
13075                                         may_have_traps = 1;
13076                                 action = ckstrdup(action);
13077                         }
13078                 }
13079                 free(trap[signo]);
13080                 trap[signo] = action;
13081                 if (signo != 0)
13082                         setsignal(signo);
13083                 INT_ON;
13084  next:
13085                 ap++;
13086         }
13087         return exitcode;
13088 }
13089
13090
13091 /* ============ Builtins */
13092
13093 #if ENABLE_ASH_HELP
13094 static int FAST_FUNC
13095 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13096 {
13097         unsigned col;
13098         unsigned i;
13099
13100         out1fmt(
13101                 "Built-in commands:\n"
13102                 "------------------\n");
13103         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13104                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13105                                         builtintab[i].name + 1);
13106                 if (col > 60) {
13107                         out1fmt("\n");
13108                         col = 0;
13109                 }
13110         }
13111 # if ENABLE_FEATURE_SH_STANDALONE
13112         {
13113                 const char *a = applet_names;
13114                 while (*a) {
13115                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13116                         if (col > 60) {
13117                                 out1fmt("\n");
13118                                 col = 0;
13119                         }
13120                         while (*a++ != '\0')
13121                                 continue;
13122                 }
13123         }
13124 # endif
13125         newline_and_flush(stdout);
13126         return EXIT_SUCCESS;
13127 }
13128 #endif
13129
13130 #if MAX_HISTORY
13131 static int FAST_FUNC
13132 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13133 {
13134         show_history(line_input_state);
13135         return EXIT_SUCCESS;
13136 }
13137 #endif
13138
13139 /*
13140  * The export and readonly commands.
13141  */
13142 static int FAST_FUNC
13143 exportcmd(int argc UNUSED_PARAM, char **argv)
13144 {
13145         struct var *vp;
13146         char *name;
13147         const char *p;
13148         char **aptr;
13149         char opt;
13150         int flag;
13151         int flag_off;
13152
13153         /* "readonly" in bash accepts, but ignores -n.
13154          * We do the same: it saves a conditional in nextopt's param.
13155          */
13156         flag_off = 0;
13157         while ((opt = nextopt("np")) != '\0') {
13158                 if (opt == 'n')
13159                         flag_off = VEXPORT;
13160         }
13161         flag = VEXPORT;
13162         if (argv[0][0] == 'r') {
13163                 flag = VREADONLY;
13164                 flag_off = 0; /* readonly ignores -n */
13165         }
13166         flag_off = ~flag_off;
13167
13168         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13169         {
13170                 aptr = argptr;
13171                 name = *aptr;
13172                 if (name) {
13173                         do {
13174                                 p = strchr(name, '=');
13175                                 if (p != NULL) {
13176                                         p++;
13177                                 } else {
13178                                         vp = *findvar(hashvar(name), name);
13179                                         if (vp) {
13180                                                 vp->flags = ((vp->flags | flag) & flag_off);
13181                                                 continue;
13182                                         }
13183                                 }
13184                                 setvar(name, p, (flag & flag_off));
13185                         } while ((name = *++aptr) != NULL);
13186                         return 0;
13187                 }
13188         }
13189
13190         /* No arguments. Show the list of exported or readonly vars.
13191          * -n is ignored.
13192          */
13193         showvars(argv[0], flag, 0);
13194         return 0;
13195 }
13196
13197 /*
13198  * Delete a function if it exists.
13199  */
13200 static void
13201 unsetfunc(const char *name)
13202 {
13203         struct tblentry *cmdp;
13204
13205         cmdp = cmdlookup(name, 0);
13206         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13207                 delete_cmd_entry();
13208 }
13209
13210 /*
13211  * The unset builtin command.  We unset the function before we unset the
13212  * variable to allow a function to be unset when there is a readonly variable
13213  * with the same name.
13214  */
13215 static int FAST_FUNC
13216 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13217 {
13218         char **ap;
13219         int i;
13220         int flag = 0;
13221         int ret = 0;
13222
13223         while ((i = nextopt("vf")) != 0) {
13224                 flag = i;
13225         }
13226
13227         for (ap = argptr; *ap; ap++) {
13228                 if (flag != 'f') {
13229                         i = unsetvar(*ap);
13230                         ret |= i;
13231                         if (!(i & 2))
13232                                 continue;
13233                 }
13234                 if (flag != 'v')
13235                         unsetfunc(*ap);
13236         }
13237         return ret & 1;
13238 }
13239
13240 static const unsigned char timescmd_str[] ALIGN1 = {
13241         ' ',  offsetof(struct tms, tms_utime),
13242         '\n', offsetof(struct tms, tms_stime),
13243         ' ',  offsetof(struct tms, tms_cutime),
13244         '\n', offsetof(struct tms, tms_cstime),
13245         0
13246 };
13247 static int FAST_FUNC
13248 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13249 {
13250         unsigned long clk_tck, s, t;
13251         const unsigned char *p;
13252         struct tms buf;
13253
13254         clk_tck = bb_clk_tck();
13255         times(&buf);
13256
13257         p = timescmd_str;
13258         do {
13259                 t = *(clock_t *)(((char *) &buf) + p[1]);
13260                 s = t / clk_tck;
13261                 t = t % clk_tck;
13262                 out1fmt("%lum%lu.%03lus%c",
13263                         s / 60, s % 60,
13264                         (t * 1000) / clk_tck,
13265                         p[0]);
13266                 p += 2;
13267         } while (*p);
13268
13269         return 0;
13270 }
13271
13272 #if ENABLE_FEATURE_SH_MATH
13273 /*
13274  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13275  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13276  *
13277  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13278  */
13279 static int FAST_FUNC
13280 letcmd(int argc UNUSED_PARAM, char **argv)
13281 {
13282         arith_t i;
13283
13284         argv++;
13285         if (!*argv)
13286                 ash_msg_and_raise_error("expression expected");
13287         do {
13288                 i = ash_arith(*argv);
13289         } while (*++argv);
13290
13291         return !i;
13292 }
13293 #endif
13294
13295 /*
13296  * The read builtin. Options:
13297  *      -r              Do not interpret '\' specially
13298  *      -s              Turn off echo (tty only)
13299  *      -n NCHARS       Read NCHARS max
13300  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13301  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13302  *      -u FD           Read from given FD instead of fd 0
13303  * This uses unbuffered input, which may be avoidable in some cases.
13304  * TODO: bash also has:
13305  *      -a ARRAY        Read into array[0],[1],etc
13306  *      -d DELIM        End on DELIM char, not newline
13307  *      -e              Use line editing (tty only)
13308  */
13309 static int FAST_FUNC
13310 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13311 {
13312         char *opt_n = NULL;
13313         char *opt_p = NULL;
13314         char *opt_t = NULL;
13315         char *opt_u = NULL;
13316         int read_flags = 0;
13317         const char *r;
13318         int i;
13319
13320         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13321                 switch (i) {
13322                 case 'p':
13323                         opt_p = optionarg;
13324                         break;
13325                 case 'n':
13326                         opt_n = optionarg;
13327                         break;
13328                 case 's':
13329                         read_flags |= BUILTIN_READ_SILENT;
13330                         break;
13331                 case 't':
13332                         opt_t = optionarg;
13333                         break;
13334                 case 'r':
13335                         read_flags |= BUILTIN_READ_RAW;
13336                         break;
13337                 case 'u':
13338                         opt_u = optionarg;
13339                         break;
13340                 default:
13341                         break;
13342                 }
13343         }
13344
13345         /* "read -s" needs to save/restore termios, can't allow ^C
13346          * to jump out of it.
13347          */
13348  again:
13349         INT_OFF;
13350         r = shell_builtin_read(setvar0,
13351                 argptr,
13352                 bltinlookup("IFS"), /* can be NULL */
13353                 read_flags,
13354                 opt_n,
13355                 opt_p,
13356                 opt_t,
13357                 opt_u
13358         );
13359         INT_ON;
13360
13361         if ((uintptr_t)r == 1 && errno == EINTR) {
13362                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13363                 if (pending_sig == 0)
13364                         goto again;
13365         }
13366
13367         if ((uintptr_t)r > 1)
13368                 ash_msg_and_raise_error(r);
13369
13370         return (uintptr_t)r;
13371 }
13372
13373 static int FAST_FUNC
13374 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13375 {
13376         static const char permuser[3] ALIGN1 = "ogu";
13377
13378         mode_t mask;
13379         int symbolic_mode = 0;
13380
13381         while (nextopt("S") != '\0') {
13382                 symbolic_mode = 1;
13383         }
13384
13385         INT_OFF;
13386         mask = umask(0);
13387         umask(mask);
13388         INT_ON;
13389
13390         if (*argptr == NULL) {
13391                 if (symbolic_mode) {
13392                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13393                         char *p = buf;
13394                         int i;
13395
13396                         i = 2;
13397                         for (;;) {
13398                                 *p++ = ',';
13399                                 *p++ = permuser[i];
13400                                 *p++ = '=';
13401                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13402                                 if (!(mask & 0400)) *p++ = 'r';
13403                                 if (!(mask & 0200)) *p++ = 'w';
13404                                 if (!(mask & 0100)) *p++ = 'x';
13405                                 mask <<= 3;
13406                                 if (--i < 0)
13407                                         break;
13408                         }
13409                         *p = '\0';
13410                         puts(buf + 1);
13411                 } else {
13412                         out1fmt("%04o\n", mask);
13413                 }
13414         } else {
13415                 char *modestr = *argptr;
13416                 /* numeric umasks are taken as-is */
13417                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13418                 if (!isdigit(modestr[0]))
13419                         mask ^= 0777;
13420                 mask = bb_parse_mode(modestr, mask);
13421                 if ((unsigned)mask > 0777) {
13422                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13423                 }
13424                 if (!isdigit(modestr[0]))
13425                         mask ^= 0777;
13426                 umask(mask);
13427         }
13428         return 0;
13429 }
13430
13431 static int FAST_FUNC
13432 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13433 {
13434         return shell_builtin_ulimit(argv);
13435 }
13436
13437 /* ============ main() and helpers */
13438
13439 /*
13440  * Called to exit the shell.
13441  */
13442 static void
13443 exitshell(void)
13444 {
13445         struct jmploc loc;
13446         char *p;
13447         int status;
13448
13449 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13450         save_history(line_input_state);
13451 #endif
13452         status = exitstatus;
13453         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13454         if (setjmp(loc.loc)) {
13455                 if (exception_type == EXEXIT)
13456                         status = exitstatus;
13457                 goto out;
13458         }
13459         exception_handler = &loc;
13460         p = trap[0];
13461         if (p) {
13462                 trap[0] = NULL;
13463                 evalskip = 0;
13464                 evalstring(p, 0);
13465                 /*free(p); - we'll exit soon */
13466         }
13467  out:
13468         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13469          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13470          */
13471         setjobctl(0);
13472         flush_stdout_stderr();
13473         _exit(status);
13474         /* NOTREACHED */
13475 }
13476
13477 static void
13478 init(void)
13479 {
13480         /* we will never free this */
13481         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13482
13483         sigmode[SIGCHLD - 1] = S_DFL;
13484         setsignal(SIGCHLD);
13485
13486         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13487          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13488          */
13489         signal(SIGHUP, SIG_DFL);
13490
13491         {
13492                 char **envp;
13493                 const char *p;
13494                 struct stat st1, st2;
13495
13496                 initvar();
13497                 for (envp = environ; envp && *envp; envp++) {
13498                         p = endofname(*envp);
13499                         if (p != *envp && *p == '=') {
13500                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13501                         }
13502                 }
13503
13504                 setvareq((char*)defoptindvar, VTEXTFIXED);
13505
13506                 setvar0("PPID", utoa(getppid()));
13507 #if BASH_SHLVL_VAR
13508                 p = lookupvar("SHLVL");
13509                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13510 #endif
13511 #if BASH_HOSTNAME_VAR
13512                 if (!lookupvar("HOSTNAME")) {
13513                         struct utsname uts;
13514                         uname(&uts);
13515                         setvar0("HOSTNAME", uts.nodename);
13516                 }
13517 #endif
13518                 p = lookupvar("PWD");
13519                 if (p) {
13520                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13521                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13522                         ) {
13523                                 p = NULL;
13524                         }
13525                 }
13526                 setpwd(p, 0);
13527         }
13528 }
13529
13530
13531 //usage:#define ash_trivial_usage
13532 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13533 //usage:#define ash_full_usage "\n\n"
13534 //usage:        "Unix shell interpreter"
13535
13536 /*
13537  * Process the shell command line arguments.
13538  */
13539 static void
13540 procargs(char **argv)
13541 {
13542         int i;
13543         const char *xminusc;
13544         char **xargv;
13545
13546         xargv = argv;
13547         arg0 = xargv[0];
13548         /* if (xargv[0]) - mmm, this is always true! */
13549                 xargv++;
13550         for (i = 0; i < NOPTS; i++)
13551                 optlist[i] = 2;
13552         argptr = xargv;
13553         if (options(/*cmdline:*/ 1)) {
13554                 /* it already printed err message */
13555                 raise_exception(EXERROR);
13556         }
13557         xargv = argptr;
13558         xminusc = minusc;
13559         if (*xargv == NULL) {
13560                 if (xminusc)
13561                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13562                 sflag = 1;
13563         }
13564         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13565                 iflag = 1;
13566         if (mflag == 2)
13567                 mflag = iflag;
13568         for (i = 0; i < NOPTS; i++)
13569                 if (optlist[i] == 2)
13570                         optlist[i] = 0;
13571 #if DEBUG == 2
13572         debug = 1;
13573 #endif
13574         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13575         if (xminusc) {
13576                 minusc = *xargv++;
13577                 if (*xargv)
13578                         goto setarg0;
13579         } else if (!sflag) {
13580                 setinputfile(*xargv, 0);
13581  setarg0:
13582                 arg0 = *xargv++;
13583                 commandname = arg0;
13584         }
13585
13586         shellparam.p = xargv;
13587 #if ENABLE_ASH_GETOPTS
13588         shellparam.optind = 1;
13589         shellparam.optoff = -1;
13590 #endif
13591         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13592         while (*xargv) {
13593                 shellparam.nparam++;
13594                 xargv++;
13595         }
13596         optschanged();
13597 }
13598
13599 /*
13600  * Read /etc/profile, ~/.profile, $ENV.
13601  */
13602 static void
13603 read_profile(const char *name)
13604 {
13605         name = expandstr(name);
13606         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13607                 return;
13608         cmdloop(0);
13609         popfile();
13610 }
13611
13612 /*
13613  * This routine is called when an error or an interrupt occurs in an
13614  * interactive shell and control is returned to the main command loop.
13615  * (In dash, this function is auto-generated by build machinery).
13616  */
13617 static void
13618 reset(void)
13619 {
13620         /* from eval.c: */
13621         evalskip = 0;
13622         loopnest = 0;
13623
13624         /* from expand.c: */
13625         ifsfree();
13626
13627         /* from input.c: */
13628         g_parsefile->left_in_buffer = 0;
13629         g_parsefile->left_in_line = 0;      /* clear input buffer */
13630         popallfiles();
13631
13632         /* from redir.c: */
13633         while (redirlist)
13634                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13635 }
13636
13637 #if PROFILE
13638 static short profile_buf[16384];
13639 extern int etext();
13640 #endif
13641
13642 /*
13643  * Main routine.  We initialize things, parse the arguments, execute
13644  * profiles if we're a login shell, and then call cmdloop to execute
13645  * commands.  The setjmp call sets up the location to jump to when an
13646  * exception occurs.  When an exception occurs the variable "state"
13647  * is used to figure out how far we had gotten.
13648  */
13649 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13650 int ash_main(int argc UNUSED_PARAM, char **argv)
13651 {
13652         volatile smallint state;
13653         struct jmploc jmploc;
13654         struct stackmark smark;
13655
13656         /* Initialize global data */
13657         INIT_G_misc();
13658         INIT_G_memstack();
13659         INIT_G_var();
13660 #if ENABLE_ASH_ALIAS
13661         INIT_G_alias();
13662 #endif
13663         INIT_G_cmdtable();
13664
13665 #if PROFILE
13666         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13667 #endif
13668
13669 #if ENABLE_FEATURE_EDITING
13670         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13671 #endif
13672         state = 0;
13673         if (setjmp(jmploc.loc)) {
13674                 smallint e;
13675                 smallint s;
13676
13677                 reset();
13678
13679                 e = exception_type;
13680                 s = state;
13681                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13682                         exitshell();
13683                 }
13684                 if (e == EXINT) {
13685                         newline_and_flush(stderr);
13686                 }
13687
13688                 popstackmark(&smark);
13689                 FORCE_INT_ON; /* enable interrupts */
13690                 if (s == 1)
13691                         goto state1;
13692                 if (s == 2)
13693                         goto state2;
13694                 if (s == 3)
13695                         goto state3;
13696                 goto state4;
13697         }
13698         exception_handler = &jmploc;
13699         rootpid = getpid();
13700
13701         init();
13702         setstackmark(&smark);
13703         procargs(argv);
13704 #if DEBUG
13705         TRACE(("Shell args: "));
13706         trace_puts_args(argv);
13707 #endif
13708
13709         if (argv[0] && argv[0][0] == '-')
13710                 isloginsh = 1;
13711         if (isloginsh) {
13712                 const char *hp;
13713
13714                 state = 1;
13715                 read_profile("/etc/profile");
13716  state1:
13717                 state = 2;
13718                 hp = lookupvar("HOME");
13719                 if (hp)
13720                         read_profile("$HOME/.profile");
13721         }
13722  state2:
13723         state = 3;
13724         if (
13725 #ifndef linux
13726          getuid() == geteuid() && getgid() == getegid() &&
13727 #endif
13728          iflag
13729         ) {
13730                 const char *shinit = lookupvar("ENV");
13731                 if (shinit != NULL && *shinit != '\0')
13732                         read_profile(shinit);
13733         }
13734         popstackmark(&smark);
13735  state3:
13736         state = 4;
13737         if (minusc) {
13738                 /* evalstring pushes parsefile stack.
13739                  * Ensure we don't falsely claim that 0 (stdin)
13740                  * is one of stacked source fds.
13741                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13742                 // if (!sflag) g_parsefile->pf_fd = -1;
13743                 // ^^ not necessary since now we special-case fd 0
13744                 // in is_hidden_fd() to not be considered "hidden fd"
13745                 evalstring(minusc, 0);
13746         }
13747
13748         if (sflag || minusc == NULL) {
13749 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13750                 if (iflag) {
13751                         const char *hp = lookupvar("HISTFILE");
13752                         if (!hp) {
13753                                 hp = lookupvar("HOME");
13754                                 if (hp) {
13755                                         INT_OFF;
13756                                         hp = concat_path_file(hp, ".ash_history");
13757                                         setvar0("HISTFILE", hp);
13758                                         free((char*)hp);
13759                                         INT_ON;
13760                                         hp = lookupvar("HISTFILE");
13761                                 }
13762                         }
13763                         if (hp)
13764                                 line_input_state->hist_file = hp;
13765 # if ENABLE_FEATURE_SH_HISTFILESIZE
13766                         hp = lookupvar("HISTFILESIZE");
13767                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13768 # endif
13769                 }
13770 #endif
13771  state4: /* XXX ??? - why isn't this before the "if" statement */
13772                 cmdloop(1);
13773         }
13774 #if PROFILE
13775         monitor(0);
13776 #endif
13777 #ifdef GPROF
13778         {
13779                 extern void _mcleanup(void);
13780                 _mcleanup();
13781         }
13782 #endif
13783         TRACE(("End of main reached\n"));
13784         exitshell();
13785         /* NOTREACHED */
13786 }
13787
13788
13789 /*-
13790  * Copyright (c) 1989, 1991, 1993, 1994
13791  *      The Regents of the University of California.  All rights reserved.
13792  *
13793  * This code is derived from software contributed to Berkeley by
13794  * Kenneth Almquist.
13795  *
13796  * Redistribution and use in source and binary forms, with or without
13797  * modification, are permitted provided that the following conditions
13798  * are met:
13799  * 1. Redistributions of source code must retain the above copyright
13800  *    notice, this list of conditions and the following disclaimer.
13801  * 2. Redistributions in binary form must reproduce the above copyright
13802  *    notice, this list of conditions and the following disclaimer in the
13803  *    documentation and/or other materials provided with the distribution.
13804  * 3. Neither the name of the University nor the names of its contributors
13805  *    may be used to endorse or promote products derived from this software
13806  *    without specific prior written permission.
13807  *
13808  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13809  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13810  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13811  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13812  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13813  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13814  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13815  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13816  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13817  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13818  * SUCH DAMAGE.
13819  */