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