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