305fb63483855b99c369bb870579a6ba31f29b2e
[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 (78 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_BASH_SOURCE_CURDIR
55 //config:       bool "'source' and '.' builtins search current directory after $PATH"
56 //config:       default n   # do not encourage non-standard behavior
57 //config:       depends on ASH_BASH_COMPAT
58 //config:       help
59 //config:       This is not compliant with standards. Avoid if possible.
60 //config:
61 //config:config ASH_BASH_NOT_FOUND_HOOK
62 //config:       bool "command_not_found_handle hook support"
63 //config:       default y
64 //config:       depends on ASH_BASH_COMPAT
65 //config:       help
66 //config:       Enable support for the 'command_not_found_handle' hook function,
67 //config:       from GNU bash, which allows for alternative command not found
68 //config:       handling.
69 //config:
70 //config:config ASH_JOB_CONTROL
71 //config:       bool "Job control"
72 //config:       default y
73 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
74 //config:
75 //config:config ASH_ALIAS
76 //config:       bool "Alias support"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:
80 //config:config ASH_RANDOM_SUPPORT
81 //config:       bool "Pseudorandom generator and $RANDOM variable"
82 //config:       default y
83 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
84 //config:       help
85 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
86 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
87 //config:       You can reset the generator by using a specified start value.
88 //config:       After "unset RANDOM" the generator will switch off and this
89 //config:       variable will no longer have special treatment.
90 //config:
91 //config:config ASH_EXPAND_PRMT
92 //config:       bool "Expand prompt string"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       $PS# may contain volatile content, such as backquote commands.
97 //config:       This option recreates the prompt string from the environment
98 //config:       variable each time it is displayed.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable $TMOUT"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_MAIL
108 //config:       bool "Check for new mail in interactive shell"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:       help
112 //config:       Enable "check for new mail" function:
113 //config:       if set, $MAIL file and $MAILPATH list of files
114 //config:       are checked for mtime changes, and "you have mail"
115 //config:       message is printed if change is detected.
116 //config:
117 //config:config ASH_ECHO
118 //config:       bool "echo builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_PRINTF
123 //config:       bool "printf builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_TEST
128 //config:       bool "test builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:
132 //config:config ASH_HELP
133 //config:       bool "help builtin"
134 //config:       default y
135 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
136 //config:
137 //config:config ASH_GETOPTS
138 //config:       bool "getopts builtin"
139 //config:       default y
140 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
141 //config:
142 //config:config ASH_CMDCMD
143 //config:       bool "command builtin"
144 //config:       default y
145 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
146 //config:       help
147 //config:       Enable support for the 'command' builtin, which allows
148 //config:       you to run the specified command or builtin,
149 //config:       even when there is a function with the same name.
150 //config:
151 //config:endif # ash options
152
153 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
154 //                      APPLET_ODDNAME:name  main location    suid_type     help
155 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
156 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
157
158 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
159 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
160 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
161 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
162
163 /*
164  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
165  * DEBUG=2 to compile in and turn on debugging.
166  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
167  * debugging info is written to ./trace, quit signal generates core dump.
168  */
169 #define DEBUG 0
170 /* Tweak debug output verbosity here */
171 #define DEBUG_TIME 0
172 #define DEBUG_PID 1
173 #define DEBUG_SIG 1
174 #define DEBUG_INTONOFF 0
175
176 #define PROFILE 0
177
178 #define JOBS ENABLE_ASH_JOB_CONTROL
179
180 #include <fnmatch.h>
181 #include <sys/times.h>
182 #include <sys/utsname.h> /* for setting $HOSTNAME */
183 #include "busybox.h" /* for applet_names */
184 #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
185 # include "embedded_scripts.h"
186 #else
187 # define NUM_SCRIPTS 0
188 #endif
189
190 /* So far, all bash compat is controlled by one config option */
191 /* Separate defines document which part of code implements what */
192 /* function keyword */
193 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
194 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
195 /* &>file */
196 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
198 /* $'...' */
199 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
201 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
202 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
203 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
204 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
205 /* BASH_TEST2: [[ EXPR ]]
206  * Status of [[ support:
207  * We replace && and || with -a and -o
208  * TODO:
209  * singleword+noglob expansion:
210  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
211  *   [[ /bin/n* ]]; echo 0:$?
212  * -a/-o are not AND/OR ops! (they are just strings)
213  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
214  * = is glob match operator, not equality operator: STR = GLOB
215  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
216  * == same as =
217  * add =~ regex match operator: STR =~ REGEX
218  */
219 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
220 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
221 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
222 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
223 #define    BASH_EPOCH_VARS      ENABLE_ASH_BASH_COMPAT
224 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
225 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
226 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
227 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
228 #define    BASH_WAIT_N          ENABLE_ASH_BASH_COMPAT
229
230 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
231 /* Bionic at least up to version 24 has no glob() */
232 # undef  ENABLE_ASH_INTERNAL_GLOB
233 # define ENABLE_ASH_INTERNAL_GLOB 1
234 #endif
235
236 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
237 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
238 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
239 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
240 # error glob() should unbackslash them and match. uClibc does not unbackslash,
241 # error fails to match dirname, subsequently not expanding <pattern> in it.
242 // Testcase:
243 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
244 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
245 #endif
246
247 #if !ENABLE_ASH_INTERNAL_GLOB
248 # include <glob.h>
249 #endif
250
251 #include "unicode.h"
252 #include "shell_common.h"
253 #if ENABLE_FEATURE_SH_MATH
254 # include "math.h"
255 #else
256 typedef long arith_t;
257 # define ARITH_FMT "%ld"
258 #endif
259 #if ENABLE_ASH_RANDOM_SUPPORT
260 # include "random.h"
261 #else
262 # define CLEAR_RANDOM_T(rnd) ((void)0)
263 #endif
264
265 #include "NUM_APPLETS.h"
266 #if NUM_APPLETS == 1
267 /* STANDALONE does not make sense, and won't compile */
268 # undef CONFIG_FEATURE_SH_STANDALONE
269 # undef ENABLE_FEATURE_SH_STANDALONE
270 # undef IF_FEATURE_SH_STANDALONE
271 # undef IF_NOT_FEATURE_SH_STANDALONE
272 # define ENABLE_FEATURE_SH_STANDALONE 0
273 # define IF_FEATURE_SH_STANDALONE(...)
274 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
275 #endif
276
277 #ifndef F_DUPFD_CLOEXEC
278 # define F_DUPFD_CLOEXEC F_DUPFD
279 #endif
280 #ifndef O_CLOEXEC
281 # define O_CLOEXEC 0
282 #endif
283 #ifndef PIPE_BUF
284 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
285 #endif
286
287 #if !BB_MMU
288 # error "Do not even bother, ash will not run on NOMMU machine"
289 #endif
290
291 /* We use a trick to have more optimized code (fewer pointer reloads):
292  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
293  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
294  * This way, compiler in ash.c knows the pointer can not change.
295  *
296  * However, this may break on weird arches or toolchains. In this case,
297  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
298  * this optimization.
299  */
300 #ifndef BB_GLOBAL_CONST
301 # define BB_GLOBAL_CONST const
302 #endif
303
304
305 /* ============ Hash table sizes. Configurable. */
306
307 #define VTABSIZE 39
308 #define ATABSIZE 39
309 #define CMDTABLESIZE 31         /* should be prime */
310
311
312 /* ============ Shell options */
313
314 static const char *const optletters_optnames[] = {
315         "e"   "errexit",
316         "f"   "noglob",
317         "I"   "ignoreeof",
318 /* The below allowed this invocation:
319  * ash -c 'set -i; echo $-; sleep 5; echo $-'
320  * to be ^C-ed and get to interactive ash prompt.
321  * bash does not support such "set -i".
322  * In our code, this is denoted by empty long name:
323  */
324         "i"   "",
325         "m"   "monitor",
326         "n"   "noexec",
327 /* Ditto: bash has no "set -s" */
328         "s"   "",
329         "c"   "",
330         "x"   "xtrace",
331         "v"   "verbose",
332         "C"   "noclobber",
333         "a"   "allexport",
334         "b"   "notify",
335         "u"   "nounset",
336         "\0"  "vi"
337 #if BASH_PIPEFAIL
338         ,"\0"  "pipefail"
339 #endif
340 #if DEBUG
341         ,"\0"  "nolog"
342         ,"\0"  "debug"
343 #endif
344 };
345 //bash 4.4.23 also has these opts (with these defaults):
346 //braceexpand           on
347 //emacs                 on
348 //errtrace              off
349 //functrace             off
350 //hashall               on
351 //histexpand            off
352 //history               on
353 //interactive-comments  on
354 //keyword               off
355 //onecmd                off
356 //physical              off
357 //posix                 off
358 //privileged            off
359
360 #define optletters(n)  optletters_optnames[n][0]
361 #define optnames(n)   (optletters_optnames[n] + 1)
362
363 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
364
365
366 /* ============ Misc data */
367
368 #define msg_illnum "Illegal number: %s"
369
370 /*
371  * We enclose jmp_buf in a structure so that we can declare pointers to
372  * jump locations.  The global variable handler contains the location to
373  * jump to when an exception occurs, and the global variable exception_type
374  * contains a code identifying the exception.  To implement nested
375  * exception handlers, the user should save the value of handler on entry
376  * to an inner scope, set handler to point to a jmploc structure for the
377  * inner scope, and restore handler on exit from the scope.
378  */
379 struct jmploc {
380         jmp_buf loc;
381 };
382
383 struct globals_misc {
384         uint8_t exitstatus;     /* exit status of last command */
385         uint8_t back_exitstatus;/* exit status of backquoted command */
386         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
387         int rootpid;            /* pid of main shell */
388         /* shell level: 0 for the main shell, 1 for its children, and so on */
389         int shlvl;
390 #define rootshell (!shlvl)
391         int errlinno;
392
393         char *minusc;  /* argument to -c option */
394
395         char *curdir; // = nullstr;     /* current working directory */
396         char *physdir; // = nullstr;    /* physical working directory */
397
398         char *arg0; /* value of $0 */
399
400         struct jmploc *exception_handler;
401
402         volatile int suppress_int; /* counter */
403         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
404         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
405         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
406         smallint exception_type; /* kind of exception (0..5) */
407         /* exceptions */
408 #define EXINT 0         /* SIGINT received */
409 #define EXERROR 1       /* a generic error */
410 #define EXEXIT 4        /* exit the shell */
411
412         char nullstr[1];        /* zero length string */
413
414         char optlist[NOPTS];
415 #define eflag optlist[0]
416 #define fflag optlist[1]
417 #define Iflag optlist[2]
418 #define iflag optlist[3]
419 #define mflag optlist[4]
420 #define nflag optlist[5]
421 #define sflag optlist[6]
422 #define cflag optlist[7]
423 #define xflag optlist[8]
424 #define vflag optlist[9]
425 #define Cflag optlist[10]
426 #define aflag optlist[11]
427 #define bflag optlist[12]
428 #define uflag optlist[13]
429 #define viflag optlist[14]
430 #if BASH_PIPEFAIL
431 # define pipefail optlist[15]
432 #else
433 # define pipefail 0
434 #endif
435 #if DEBUG
436 # define nolog optlist[15 + BASH_PIPEFAIL]
437 # define debug optlist[16 + BASH_PIPEFAIL]
438 #endif
439
440         /* trap handler commands */
441         /*
442          * Sigmode records the current value of the signal handlers for the various
443          * modes.  A value of zero means that the current handler is not known.
444          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
445          */
446         char sigmode[NSIG - 1];
447 #define S_DFL      1            /* default signal handling (SIG_DFL) */
448 #define S_CATCH    2            /* signal is caught */
449 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
450 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
451
452         /* indicates specified signal received */
453         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
454         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
455         char *trap[NSIG];
456         char **trap_ptr;        /* used only by "trap hack" */
457
458         /* Rarely referenced stuff */
459 #if ENABLE_ASH_RANDOM_SUPPORT
460         random_t random_gen;
461 #endif
462         pid_t backgndpid;        /* pid of last background process */
463 };
464 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
465 #define G_misc (*ash_ptr_to_globals_misc)
466 #define exitstatus        (G_misc.exitstatus )
467 #define back_exitstatus   (G_misc.back_exitstatus )
468 #define job_warning       (G_misc.job_warning)
469 #define rootpid     (G_misc.rootpid    )
470 #define shlvl       (G_misc.shlvl      )
471 #define errlinno    (G_misc.errlinno   )
472 #define minusc      (G_misc.minusc     )
473 #define curdir      (G_misc.curdir     )
474 #define physdir     (G_misc.physdir    )
475 #define arg0        (G_misc.arg0       )
476 #define exception_handler (G_misc.exception_handler)
477 #define exception_type    (G_misc.exception_type   )
478 #define suppress_int      (G_misc.suppress_int     )
479 #define pending_int       (G_misc.pending_int      )
480 #define got_sigchld       (G_misc.got_sigchld      )
481 #define pending_sig       (G_misc.pending_sig      )
482 #define nullstr     (G_misc.nullstr    )
483 #define optlist     (G_misc.optlist    )
484 #define sigmode     (G_misc.sigmode    )
485 #define gotsig      (G_misc.gotsig     )
486 #define may_have_traps    (G_misc.may_have_traps   )
487 #define trap        (G_misc.trap       )
488 #define trap_ptr    (G_misc.trap_ptr   )
489 #define random_gen  (G_misc.random_gen )
490 #define backgndpid  (G_misc.backgndpid )
491 #define INIT_G_misc() do { \
492         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
493         barrier(); \
494         curdir = nullstr; \
495         physdir = nullstr; \
496         trap_ptr = trap; \
497 } while (0)
498
499
500 /* ============ DEBUG */
501 #if DEBUG
502 static void trace_printf(const char *fmt, ...);
503 static void trace_vprintf(const char *fmt, va_list va);
504 # define TRACE(param)    trace_printf param
505 # define TRACEV(param)   trace_vprintf param
506 # define close(fd) do { \
507         int dfd = (fd); \
508         if (close(dfd) < 0) \
509                 bb_error_msg("bug on %d: closing %d(0x%x)", \
510                         __LINE__, dfd, dfd); \
511 } while (0)
512 #else
513 # define TRACE(param)
514 # define TRACEV(param)
515 #endif
516
517
518 /* ============ Utility functions */
519 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
520 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
521
522 static int
523 isdigit_str9(const char *str)
524 {
525         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
526         while (--maxlen && isdigit(*str))
527                 str++;
528         return (*str == '\0');
529 }
530
531 static const char *
532 var_end(const char *var)
533 {
534         while (*var)
535                 if (*var++ == '=')
536                         break;
537         return var;
538 }
539
540
541 /* ============ Interrupts / exceptions */
542
543 static void exitshell(void) NORETURN;
544
545 /*
546  * These macros allow the user to suspend the handling of interrupt signals
547  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
548  * much more efficient and portable.  (But hacking the kernel is so much
549  * more fun than worrying about efficiency and portability. :-))
550  */
551 #if DEBUG_INTONOFF
552 # define INT_OFF do { \
553         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
554         suppress_int++; \
555         barrier(); \
556 } while (0)
557 #else
558 # define INT_OFF do { \
559         suppress_int++; \
560         barrier(); \
561 } while (0)
562 #endif
563
564 /*
565  * Called to raise an exception.  Since C doesn't include exceptions, we
566  * just do a longjmp to the exception handler.  The type of exception is
567  * stored in the global variable "exception_type".
568  */
569 static void raise_exception(int) NORETURN;
570 static void
571 raise_exception(int e)
572 {
573 #if DEBUG
574         if (exception_handler == NULL)
575                 abort();
576 #endif
577         INT_OFF;
578         exception_type = e;
579         longjmp(exception_handler->loc, 1);
580 }
581 #if DEBUG
582 #define raise_exception(e) do { \
583         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
584         raise_exception(e); \
585 } while (0)
586 #endif
587
588 /*
589  * Called when a SIGINT is received.  (If the user specifies
590  * that SIGINT is to be trapped or ignored using the trap builtin, then
591  * this routine is not called.)  Suppressint is nonzero when interrupts
592  * are held using the INT_OFF macro.  (The test for iflag is just
593  * defensive programming.)
594  */
595 static void raise_interrupt(void) NORETURN;
596 static void
597 raise_interrupt(void)
598 {
599         pending_int = 0;
600         /* Signal is not automatically unmasked after it is raised,
601          * do it ourself - unmask all signals */
602         sigprocmask_allsigs(SIG_UNBLOCK);
603         /* pending_sig = 0; - now done in signal_handler() */
604
605         if (!(rootshell && iflag)) {
606                 /* Kill ourself with SIGINT */
607                 signal(SIGINT, SIG_DFL);
608                 raise(SIGINT);
609         }
610         /* bash: ^C even on empty command line sets $? */
611         exitstatus = SIGINT + 128;
612         raise_exception(EXINT);
613         /* NOTREACHED */
614 }
615 #if DEBUG
616 #define raise_interrupt() do { \
617         TRACE(("raising interrupt on line %d\n", __LINE__)); \
618         raise_interrupt(); \
619 } while (0)
620 #endif
621
622 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
623 int_on(void)
624 {
625         barrier();
626         if (--suppress_int == 0 && pending_int) {
627                 raise_interrupt();
628         }
629 }
630 #if DEBUG_INTONOFF
631 # define INT_ON do { \
632         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
633         int_on(); \
634 } while (0)
635 #else
636 # define INT_ON int_on()
637 #endif
638 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
639 force_int_on(void)
640 {
641         barrier();
642         suppress_int = 0;
643         if (pending_int)
644                 raise_interrupt();
645 }
646 #define FORCE_INT_ON force_int_on()
647
648 #define SAVE_INT(v) ((v) = suppress_int)
649
650 #define RESTORE_INT(v) do { \
651         barrier(); \
652         suppress_int = (v); \
653         if (suppress_int == 0 && pending_int) \
654                 raise_interrupt(); \
655 } while (0)
656
657
658 /* ============ Stdout/stderr output */
659
660 static void
661 outstr(const char *p, FILE *file)
662 {
663         INT_OFF;
664         fputs(p, file);
665         INT_ON;
666 }
667
668 static void
669 flush_stdout_stderr(void)
670 {
671         INT_OFF;
672         fflush_all();
673         INT_ON;
674 }
675
676 /* Was called outcslow(c,FILE*), but c was always '\n' */
677 static void
678 newline_and_flush(FILE *dest)
679 {
680         INT_OFF;
681         putc('\n', dest);
682         fflush(dest);
683         INT_ON;
684 }
685
686 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
687 static int
688 out1fmt(const char *fmt, ...)
689 {
690         va_list ap;
691         int r;
692
693         INT_OFF;
694         va_start(ap, fmt);
695         r = vprintf(fmt, ap);
696         va_end(ap);
697         INT_ON;
698         return r;
699 }
700
701 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
702 static int
703 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
704 {
705         va_list ap;
706         int ret;
707
708         INT_OFF;
709         va_start(ap, fmt);
710         ret = vsnprintf(outbuf, length, fmt, ap);
711         va_end(ap);
712         INT_ON;
713         return ret;
714 }
715
716 static void
717 out1str(const char *p)
718 {
719         outstr(p, stdout);
720 }
721
722 static void
723 out2str(const char *p)
724 {
725         outstr(p, stderr);
726         flush_stdout_stderr();
727 }
728
729
730 /* ============ Parser structures */
731
732 /* control characters in argument strings */
733 #define CTL_FIRST CTLESC
734 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
735 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
736 #define CTLENDVAR    ((unsigned char)'\203')
737 #define CTLBACKQ     ((unsigned char)'\204')
738 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
739 #define CTLENDARI    ((unsigned char)'\207')
740 #define CTLQUOTEMARK ((unsigned char)'\210')
741 #define CTL_LAST CTLQUOTEMARK
742
743 /* variable substitution byte (follows CTLVAR) */
744 #define VSTYPE  0x0f            /* type of variable substitution */
745 #define VSNUL   0x10            /* colon--treat the empty string as unset */
746
747 /* values of VSTYPE field */
748 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
749 #define VSMINUS         0x2     /* ${var-text} */
750 #define VSPLUS          0x3     /* ${var+text} */
751 #define VSQUESTION      0x4     /* ${var?message} */
752 #define VSASSIGN        0x5     /* ${var=text} */
753 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
754 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
755 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
756 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
757 #define VSLENGTH        0xa     /* ${#var} */
758 #if BASH_SUBSTR
759 #define VSSUBSTR        0xc     /* ${var:position:length} */
760 #endif
761 #if BASH_PATTERN_SUBST
762 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
763 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
764 #endif
765
766 static const char dolatstr[] ALIGN1 = {
767         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
768 };
769 #define DOLATSTRLEN 6
770
771 #define NCMD      0
772 #define NPIPE     1
773 #define NREDIR    2
774 #define NBACKGND  3
775 #define NSUBSHELL 4
776 #define NAND      5
777 #define NOR       6
778 #define NSEMI     7
779 #define NIF       8
780 #define NWHILE    9
781 #define NUNTIL   10
782 #define NFOR     11
783 #define NCASE    12
784 #define NCLIST   13
785 #define NDEFUN   14
786 #define NARG     15
787 #define NTO      16
788 #if BASH_REDIR_OUTPUT
789 #define NTO2     17
790 #endif
791 #define NCLOBBER 18
792 #define NFROM    19
793 #define NFROMTO  20
794 #define NAPPEND  21
795 #define NTOFD    22
796 #define NFROMFD  23
797 #define NHERE    24
798 #define NXHERE   25
799 #define NNOT     26
800 #define N_NUMBER 27
801
802 union node;
803
804 struct ncmd {
805         smallint type; /* Nxxxx */
806         int linno;
807         union node *assign;
808         union node *args;
809         union node *redirect;
810 };
811
812 struct npipe {
813         smallint type;
814         smallint pipe_backgnd;
815         struct nodelist *cmdlist;
816 };
817
818 struct nredir {
819         smallint type;
820         int linno;
821         union node *n;
822         union node *redirect;
823 };
824
825 struct nbinary {
826         smallint type;
827         union node *ch1;
828         union node *ch2;
829 };
830
831 struct nif {
832         smallint type;
833         union node *test;
834         union node *ifpart;
835         union node *elsepart;
836 };
837
838 struct nfor {
839         smallint type;
840         int linno;
841         union node *args;
842         union node *body;
843         char *var;
844 };
845
846 struct ncase {
847         smallint type;
848         int linno;
849         union node *expr;
850         union node *cases;
851 };
852
853 struct nclist {
854         smallint type;
855         union node *next;
856         union node *pattern;
857         union node *body;
858 };
859
860 struct ndefun {
861         smallint type;
862         int linno;
863         char *text;
864         union node *body;
865 };
866
867 struct narg {
868         smallint type;
869         union node *next;
870         char *text;
871         struct nodelist *backquote;
872 };
873
874 /* nfile and ndup layout must match!
875  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
876  * that it is actually NTO2 (>&file), and change its type.
877  */
878 struct nfile {
879         smallint type;
880         union node *next;
881         int fd;
882         int _unused_dupfd;
883         union node *fname;
884         char *expfname;
885 };
886
887 struct ndup {
888         smallint type;
889         union node *next;
890         int fd;
891         int dupfd;
892         union node *vname;
893         char *_unused_expfname;
894 };
895
896 struct nhere {
897         smallint type;
898         union node *next;
899         int fd;
900         union node *doc;
901 };
902
903 struct nnot {
904         smallint type;
905         union node *com;
906 };
907
908 union node {
909         smallint type;
910         struct ncmd ncmd;
911         struct npipe npipe;
912         struct nredir nredir;
913         struct nbinary nbinary;
914         struct nif nif;
915         struct nfor nfor;
916         struct ncase ncase;
917         struct nclist nclist;
918         struct ndefun ndefun;
919         struct narg narg;
920         struct nfile nfile;
921         struct ndup ndup;
922         struct nhere nhere;
923         struct nnot nnot;
924 };
925
926 /*
927  * NODE_EOF is returned by parsecmd when it encounters an end of file.
928  * It must be distinct from NULL.
929  */
930 #define NODE_EOF ((union node *) -1L)
931
932 struct nodelist {
933         struct nodelist *next;
934         union node *n;
935 };
936
937 struct funcnode {
938         int count;
939         union node n;
940 };
941
942 /*
943  * Free a parse tree.
944  */
945 static void
946 freefunc(struct funcnode *f)
947 {
948         if (f && --f->count < 0)
949                 free(f);
950 }
951
952
953 /* ============ Debugging output */
954
955 #if DEBUG
956
957 static FILE *tracefile;
958
959 static void
960 trace_printf(const char *fmt, ...)
961 {
962         va_list va;
963
964         if (debug != 1)
965                 return;
966         if (DEBUG_TIME)
967                 fprintf(tracefile, "%u ", (int) time(NULL));
968         if (DEBUG_PID)
969                 fprintf(tracefile, "[%u] ", (int) getpid());
970         if (DEBUG_SIG)
971                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
972         va_start(va, fmt);
973         vfprintf(tracefile, fmt, va);
974         va_end(va);
975 }
976
977 static void
978 trace_vprintf(const char *fmt, va_list va)
979 {
980         if (debug != 1)
981                 return;
982         vfprintf(tracefile, fmt, va);
983         fprintf(tracefile, "\n");
984 }
985
986 static void
987 trace_puts(const char *s)
988 {
989         if (debug != 1)
990                 return;
991         fputs(s, tracefile);
992 }
993
994 static void
995 trace_puts_quoted(char *s)
996 {
997         char *p;
998         char c;
999
1000         if (debug != 1)
1001                 return;
1002         putc('"', tracefile);
1003         for (p = s; *p; p++) {
1004                 switch ((unsigned char)*p) {
1005                 case '\n': c = 'n'; goto backslash;
1006                 case '\t': c = 't'; goto backslash;
1007                 case '\r': c = 'r'; goto backslash;
1008                 case '\"': c = '\"'; goto backslash;
1009                 case '\\': c = '\\'; goto backslash;
1010                 case CTLESC: c = 'e'; goto backslash;
1011                 case CTLVAR: c = 'v'; goto backslash;
1012                 case CTLBACKQ: c = 'q'; goto backslash;
1013  backslash:
1014                         putc('\\', tracefile);
1015                         putc(c, tracefile);
1016                         break;
1017                 default:
1018                         if (*p >= ' ' && *p <= '~')
1019                                 putc(*p, tracefile);
1020                         else {
1021                                 putc('\\', tracefile);
1022                                 putc((*p >> 6) & 03, tracefile);
1023                                 putc((*p >> 3) & 07, tracefile);
1024                                 putc(*p & 07, tracefile);
1025                         }
1026                         break;
1027                 }
1028         }
1029         putc('"', tracefile);
1030 }
1031
1032 static void
1033 trace_puts_args(char **ap)
1034 {
1035         if (debug != 1)
1036                 return;
1037         if (!*ap)
1038                 return;
1039         while (1) {
1040                 trace_puts_quoted(*ap);
1041                 if (!*++ap) {
1042                         putc('\n', tracefile);
1043                         break;
1044                 }
1045                 putc(' ', tracefile);
1046         }
1047 }
1048
1049 static void
1050 opentrace(void)
1051 {
1052         char s[100];
1053 #ifdef O_APPEND
1054         int flags;
1055 #endif
1056
1057         if (debug != 1) {
1058                 if (tracefile)
1059                         fflush(tracefile);
1060                 /* leave open because libedit might be using it */
1061                 return;
1062         }
1063         strcpy(s, "./trace");
1064         if (tracefile) {
1065                 if (!freopen(s, "a", tracefile)) {
1066                         fprintf(stderr, "Can't re-open %s\n", s);
1067                         debug = 0;
1068                         return;
1069                 }
1070         } else {
1071                 tracefile = fopen(s, "a");
1072                 if (tracefile == NULL) {
1073                         fprintf(stderr, "Can't open %s\n", s);
1074                         debug = 0;
1075                         return;
1076                 }
1077         }
1078 #ifdef O_APPEND
1079         flags = fcntl(fileno(tracefile), F_GETFL);
1080         if (flags >= 0)
1081                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1082 #endif
1083         setlinebuf(tracefile);
1084         fputs("\nTracing started.\n", tracefile);
1085 }
1086
1087 static void
1088 indent(int amount, char *pfx, FILE *fp)
1089 {
1090         int i;
1091
1092         for (i = 0; i < amount; i++) {
1093                 if (pfx && i == amount - 1)
1094                         fputs(pfx, fp);
1095                 putc('\t', fp);
1096         }
1097 }
1098
1099 /* little circular references here... */
1100 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1101
1102 static void
1103 sharg(union node *arg, FILE *fp)
1104 {
1105         char *p;
1106         struct nodelist *bqlist;
1107         unsigned char subtype;
1108
1109         if (arg->type != NARG) {
1110                 out1fmt("<node type %d>\n", arg->type);
1111                 abort();
1112         }
1113         bqlist = arg->narg.backquote;
1114         for (p = arg->narg.text; *p; p++) {
1115                 switch ((unsigned char)*p) {
1116                 case CTLESC:
1117                         p++;
1118                         putc(*p, fp);
1119                         break;
1120                 case CTLVAR:
1121                         putc('$', fp);
1122                         putc('{', fp);
1123                         subtype = *++p;
1124                         if (subtype == VSLENGTH)
1125                                 putc('#', fp);
1126
1127                         while (*p != '=') {
1128                                 putc(*p, fp);
1129                                 p++;
1130                         }
1131
1132                         if (subtype & VSNUL)
1133                                 putc(':', fp);
1134
1135                         switch (subtype & VSTYPE) {
1136                         case VSNORMAL:
1137                                 putc('}', fp);
1138                                 break;
1139                         case VSMINUS:
1140                                 putc('-', fp);
1141                                 break;
1142                         case VSPLUS:
1143                                 putc('+', fp);
1144                                 break;
1145                         case VSQUESTION:
1146                                 putc('?', fp);
1147                                 break;
1148                         case VSASSIGN:
1149                                 putc('=', fp);
1150                                 break;
1151                         case VSTRIMLEFT:
1152                                 putc('#', fp);
1153                                 break;
1154                         case VSTRIMLEFTMAX:
1155                                 putc('#', fp);
1156                                 putc('#', fp);
1157                                 break;
1158                         case VSTRIMRIGHT:
1159                                 putc('%', fp);
1160                                 break;
1161                         case VSTRIMRIGHTMAX:
1162                                 putc('%', fp);
1163                                 putc('%', fp);
1164                                 break;
1165                         case VSLENGTH:
1166                                 break;
1167                         default:
1168                                 out1fmt("<subtype %d>", subtype);
1169                         }
1170                         break;
1171                 case CTLENDVAR:
1172                         putc('}', fp);
1173                         break;
1174                 case CTLBACKQ:
1175                         putc('$', fp);
1176                         putc('(', fp);
1177                         shtree(bqlist->n, -1, NULL, fp);
1178                         putc(')', fp);
1179                         break;
1180                 default:
1181                         putc(*p, fp);
1182                         break;
1183                 }
1184         }
1185 }
1186
1187 static void
1188 shcmd(union node *cmd, FILE *fp)
1189 {
1190         union node *np;
1191         int first;
1192         const char *s;
1193         int dftfd;
1194
1195         first = 1;
1196         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1197                 if (!first)
1198                         putc(' ', fp);
1199                 sharg(np, fp);
1200                 first = 0;
1201         }
1202         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1203                 if (!first)
1204                         putc(' ', fp);
1205                 dftfd = 0;
1206                 switch (np->nfile.type) {
1207                 case NTO:      s = ">>"+1; dftfd = 1; break;
1208                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1209                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1210 #if BASH_REDIR_OUTPUT
1211                 case NTO2:
1212 #endif
1213                 case NTOFD:    s = ">&"; dftfd = 1; break;
1214                 case NFROM:    s = "<"; break;
1215                 case NFROMFD:  s = "<&"; break;
1216                 case NFROMTO:  s = "<>"; break;
1217                 default:       s = "*error*"; break;
1218                 }
1219                 if (np->nfile.fd != dftfd)
1220                         fprintf(fp, "%d", np->nfile.fd);
1221                 fputs(s, fp);
1222                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1223                         fprintf(fp, "%d", np->ndup.dupfd);
1224                 } else {
1225                         sharg(np->nfile.fname, fp);
1226                 }
1227                 first = 0;
1228         }
1229 }
1230
1231 static void
1232 shtree(union node *n, int ind, char *pfx, FILE *fp)
1233 {
1234         struct nodelist *lp;
1235         const char *s;
1236
1237         if (n == NULL)
1238                 return;
1239
1240         indent(ind, pfx, fp);
1241
1242         if (n == NODE_EOF) {
1243                 fputs("<EOF>", fp);
1244                 return;
1245         }
1246
1247         switch (n->type) {
1248         case NSEMI:
1249                 s = "; ";
1250                 goto binop;
1251         case NAND:
1252                 s = " && ";
1253                 goto binop;
1254         case NOR:
1255                 s = " || ";
1256  binop:
1257                 shtree(n->nbinary.ch1, ind, NULL, fp);
1258                 /* if (ind < 0) */
1259                         fputs(s, fp);
1260                 shtree(n->nbinary.ch2, ind, NULL, fp);
1261                 break;
1262         case NCMD:
1263                 shcmd(n, fp);
1264                 if (ind >= 0)
1265                         putc('\n', fp);
1266                 break;
1267         case NPIPE:
1268                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1269                         shtree(lp->n, 0, NULL, fp);
1270                         if (lp->next)
1271                                 fputs(" | ", fp);
1272                 }
1273                 if (n->npipe.pipe_backgnd)
1274                         fputs(" &", fp);
1275                 if (ind >= 0)
1276                         putc('\n', fp);
1277                 break;
1278         default:
1279                 fprintf(fp, "<node type %d>", n->type);
1280                 if (ind >= 0)
1281                         putc('\n', fp);
1282                 break;
1283         }
1284 }
1285
1286 static void
1287 showtree(union node *n)
1288 {
1289         trace_puts("showtree called\n");
1290         shtree(n, 1, NULL, stderr);
1291 }
1292
1293 #endif /* DEBUG */
1294
1295
1296 /* ============ Parser data */
1297
1298 /*
1299  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1300  */
1301 struct strlist {
1302         struct strlist *next;
1303         char *text;
1304 };
1305
1306 struct alias;
1307
1308 struct strpush {
1309         struct strpush *prev;   /* preceding string on stack */
1310         char *prev_string;
1311         int prev_left_in_line;
1312 #if ENABLE_ASH_ALIAS
1313         struct alias *ap;       /* if push was associated with an alias */
1314 #endif
1315         char *string;           /* remember the string since it may change */
1316
1317         /* Remember last two characters for pungetc. */
1318         int lastc[2];
1319
1320         /* Number of outstanding calls to pungetc. */
1321         int unget;
1322 };
1323
1324 /*
1325  * The parsefile structure pointed to by the global variable parsefile
1326  * contains information about the current file being read.
1327  */
1328 struct parsefile {
1329         struct parsefile *prev; /* preceding file on stack */
1330         int linno;              /* current line */
1331         int pf_fd;              /* file descriptor (or -1 if string) */
1332         int left_in_line;       /* number of chars left in this line */
1333         int left_in_buffer;     /* number of chars left in this buffer past the line */
1334         char *next_to_pgetc;    /* next char in buffer */
1335         char *buf;              /* input buffer */
1336         struct strpush *strpush; /* for pushing strings at this level */
1337         struct strpush basestrpush; /* so pushing one is fast */
1338
1339         /* Remember last two characters for pungetc. */
1340         int lastc[2];
1341
1342         /* Number of outstanding calls to pungetc. */
1343         int unget;
1344 };
1345
1346 static struct parsefile basepf;        /* top level input file */
1347 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1348 static char *commandname;              /* currently executing command */
1349
1350
1351 /* ============ Message printing */
1352
1353 static void
1354 ash_vmsg(const char *msg, va_list ap)
1355 {
1356         fprintf(stderr, "%s: ", arg0);
1357         if (commandname) {
1358                 if (strcmp(arg0, commandname))
1359                         fprintf(stderr, "%s: ", commandname);
1360                 if (!iflag || g_parsefile->pf_fd > 0)
1361                         fprintf(stderr, "line %d: ", errlinno);
1362         }
1363         vfprintf(stderr, msg, ap);
1364         newline_and_flush(stderr);
1365 }
1366
1367 /*
1368  * Exverror is called to raise the error exception.  If the second argument
1369  * is not NULL then error prints an error message using printf style
1370  * formatting.  It then raises the error exception.
1371  */
1372 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1373 static void
1374 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1375 {
1376 #if DEBUG
1377         if (msg) {
1378                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1379                 TRACEV((msg, ap));
1380         } else
1381                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1382         if (msg)
1383 #endif
1384                 ash_vmsg(msg, ap);
1385
1386         flush_stdout_stderr();
1387         raise_exception(cond);
1388         /* NOTREACHED */
1389 }
1390
1391 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1392 static void
1393 ash_msg_and_raise_error(const char *msg, ...)
1394 {
1395         va_list ap;
1396
1397         exitstatus = 2;
1398
1399         va_start(ap, msg);
1400         ash_vmsg_and_raise(EXERROR, msg, ap);
1401         /* NOTREACHED */
1402         va_end(ap);
1403 }
1404
1405 /*
1406  * 'fmt' must be a string literal.
1407  */
1408 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1409
1410 static void raise_error_syntax(const char *) NORETURN;
1411 static void
1412 raise_error_syntax(const char *msg)
1413 {
1414         errlinno = g_parsefile->linno;
1415         ash_msg_and_raise_error("syntax error: %s", msg);
1416         /* NOTREACHED */
1417 }
1418
1419 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1420 static void
1421 ash_msg_and_raise(int cond, const char *msg, ...)
1422 {
1423         va_list ap;
1424
1425         va_start(ap, msg);
1426         ash_vmsg_and_raise(cond, msg, ap);
1427         /* NOTREACHED */
1428         va_end(ap);
1429 }
1430
1431 /*
1432  * error/warning routines for external builtins
1433  */
1434 static void
1435 ash_msg(const char *fmt, ...)
1436 {
1437         va_list ap;
1438
1439         va_start(ap, fmt);
1440         ash_vmsg(fmt, ap);
1441         va_end(ap);
1442 }
1443
1444 /*
1445  * Return a string describing an error.  The returned string may be a
1446  * pointer to a static buffer that will be overwritten on the next call.
1447  * Action describes the operation that got the error.
1448  */
1449 static const char *
1450 errmsg(int e, const char *em)
1451 {
1452         if (e == ENOENT || e == ENOTDIR) {
1453                 return em;
1454         }
1455         return strerror(e);
1456 }
1457
1458
1459 /* ============ Memory allocation */
1460
1461 #if 0
1462 /* I consider these wrappers nearly useless:
1463  * ok, they return you to nearest exception handler, but
1464  * how much memory do you leak in the process, making
1465  * memory starvation worse?
1466  */
1467 static void *
1468 ckrealloc(void * p, size_t nbytes)
1469 {
1470         p = realloc(p, nbytes);
1471         if (!p)
1472                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1473         return p;
1474 }
1475
1476 static void *
1477 ckmalloc(size_t nbytes)
1478 {
1479         return ckrealloc(NULL, nbytes);
1480 }
1481
1482 static void *
1483 ckzalloc(size_t nbytes)
1484 {
1485         return memset(ckmalloc(nbytes), 0, nbytes);
1486 }
1487
1488 static char *
1489 ckstrdup(const char *s)
1490 {
1491         char *p = strdup(s);
1492         if (!p)
1493                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1494         return p;
1495 }
1496 #else
1497 /* Using bbox equivalents. They exit if out of memory */
1498 # define ckrealloc xrealloc
1499 # define ckmalloc  xmalloc
1500 # define ckzalloc  xzalloc
1501 # define ckstrdup  xstrdup
1502 #endif
1503
1504 /*
1505  * It appears that grabstackstr() will barf with such alignments
1506  * because stalloc() will return a string allocated in a new stackblock.
1507  */
1508 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1509 enum {
1510         /* Most machines require the value returned from malloc to be aligned
1511          * in some way.  The following macro will get this right
1512          * on many machines.  */
1513         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1514         /* Minimum size of a block */
1515         MINSIZE = SHELL_ALIGN(504),
1516 };
1517
1518 struct stack_block {
1519         struct stack_block *prev;
1520         char space[MINSIZE];
1521 };
1522
1523 struct stackmark {
1524         struct stack_block *stackp;
1525         char *stacknxt;
1526         size_t stacknleft;
1527 };
1528
1529
1530 struct globals_memstack {
1531         struct stack_block *g_stackp; // = &stackbase;
1532         char *g_stacknxt; // = stackbase.space;
1533         char *sstrend; // = stackbase.space + MINSIZE;
1534         size_t g_stacknleft; // = MINSIZE;
1535         struct stack_block stackbase;
1536 };
1537 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1538 #define G_memstack (*ash_ptr_to_globals_memstack)
1539 #define g_stackp     (G_memstack.g_stackp    )
1540 #define g_stacknxt   (G_memstack.g_stacknxt  )
1541 #define sstrend      (G_memstack.sstrend     )
1542 #define g_stacknleft (G_memstack.g_stacknleft)
1543 #define stackbase    (G_memstack.stackbase   )
1544 #define INIT_G_memstack() do { \
1545         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1546         barrier(); \
1547         g_stackp = &stackbase; \
1548         g_stacknxt = stackbase.space; \
1549         g_stacknleft = MINSIZE; \
1550         sstrend = stackbase.space + MINSIZE; \
1551 } while (0)
1552
1553
1554 #define stackblock()     ((void *)g_stacknxt)
1555 #define stackblocksize() g_stacknleft
1556
1557 /*
1558  * Parse trees for commands are allocated in lifo order, so we use a stack
1559  * to make this more efficient, and also to avoid all sorts of exception
1560  * handling code to handle interrupts in the middle of a parse.
1561  *
1562  * The size 504 was chosen because the Ultrix malloc handles that size
1563  * well.
1564  */
1565 static void *
1566 stalloc(size_t nbytes)
1567 {
1568         char *p;
1569         size_t aligned;
1570
1571         aligned = SHELL_ALIGN(nbytes);
1572         if (aligned > g_stacknleft) {
1573                 size_t len;
1574                 size_t blocksize;
1575                 struct stack_block *sp;
1576
1577                 blocksize = aligned;
1578                 if (blocksize < MINSIZE)
1579                         blocksize = MINSIZE;
1580                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1581                 if (len < blocksize)
1582                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1583                 INT_OFF;
1584                 sp = ckmalloc(len);
1585                 sp->prev = g_stackp;
1586                 g_stacknxt = sp->space;
1587                 g_stacknleft = blocksize;
1588                 sstrend = g_stacknxt + blocksize;
1589                 g_stackp = sp;
1590                 INT_ON;
1591         }
1592         p = g_stacknxt;
1593         g_stacknxt += aligned;
1594         g_stacknleft -= aligned;
1595         return p;
1596 }
1597
1598 static void *
1599 stzalloc(size_t nbytes)
1600 {
1601         return memset(stalloc(nbytes), 0, nbytes);
1602 }
1603
1604 static void
1605 stunalloc(void *p)
1606 {
1607 #if DEBUG
1608         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1609                 write(STDERR_FILENO, "stunalloc\n", 10);
1610                 abort();
1611         }
1612 #endif
1613         g_stacknleft += g_stacknxt - (char *)p;
1614         g_stacknxt = p;
1615 }
1616
1617 /*
1618  * Like strdup but works with the ash stack.
1619  */
1620 static char *
1621 sstrdup(const char *p)
1622 {
1623         size_t len = strlen(p) + 1;
1624         return memcpy(stalloc(len), p, len);
1625 }
1626
1627 static ALWAYS_INLINE void
1628 grabstackblock(size_t len)
1629 {
1630         stalloc(len);
1631 }
1632
1633 static void
1634 pushstackmark(struct stackmark *mark, size_t len)
1635 {
1636         mark->stackp = g_stackp;
1637         mark->stacknxt = g_stacknxt;
1638         mark->stacknleft = g_stacknleft;
1639         grabstackblock(len);
1640 }
1641
1642 static void
1643 setstackmark(struct stackmark *mark)
1644 {
1645         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1646 }
1647
1648 static void
1649 popstackmark(struct stackmark *mark)
1650 {
1651         struct stack_block *sp;
1652
1653         if (!mark->stackp)
1654                 return;
1655
1656         INT_OFF;
1657         while (g_stackp != mark->stackp) {
1658                 sp = g_stackp;
1659                 g_stackp = sp->prev;
1660                 free(sp);
1661         }
1662         g_stacknxt = mark->stacknxt;
1663         g_stacknleft = mark->stacknleft;
1664         sstrend = mark->stacknxt + mark->stacknleft;
1665         INT_ON;
1666 }
1667
1668 /*
1669  * When the parser reads in a string, it wants to stick the string on the
1670  * stack and only adjust the stack pointer when it knows how big the
1671  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1672  * of space on top of the stack and stackblocklen returns the length of
1673  * this block.  Growstackblock will grow this space by at least one byte,
1674  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1675  * part of the block that has been used.
1676  */
1677 static void
1678 growstackblock(void)
1679 {
1680         size_t newlen;
1681
1682         newlen = g_stacknleft * 2;
1683         if (newlen < g_stacknleft)
1684                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1685         if (newlen < 128)
1686                 newlen += 128;
1687
1688         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1689                 struct stack_block *sp;
1690                 struct stack_block *prevstackp;
1691                 size_t grosslen;
1692
1693                 INT_OFF;
1694                 sp = g_stackp;
1695                 prevstackp = sp->prev;
1696                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1697                 sp = ckrealloc(sp, grosslen);
1698                 sp->prev = prevstackp;
1699                 g_stackp = sp;
1700                 g_stacknxt = sp->space;
1701                 g_stacknleft = newlen;
1702                 sstrend = sp->space + newlen;
1703                 INT_ON;
1704         } else {
1705                 char *oldspace = g_stacknxt;
1706                 size_t oldlen = g_stacknleft;
1707                 char *p = stalloc(newlen);
1708
1709                 /* free the space we just allocated */
1710                 g_stacknxt = memcpy(p, oldspace, oldlen);
1711                 g_stacknleft += newlen;
1712         }
1713 }
1714
1715 /*
1716  * The following routines are somewhat easier to use than the above.
1717  * The user declares a variable of type STACKSTR, which may be declared
1718  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1719  * the user uses the macro STPUTC to add characters to the string.  In
1720  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1721  * grown as necessary.  When the user is done, she can just leave the
1722  * string there and refer to it using stackblock().  Or she can allocate
1723  * the space for it using grabstackstr().  If it is necessary to allow
1724  * someone else to use the stack temporarily and then continue to grow
1725  * the string, the user should use grabstack to allocate the space, and
1726  * then call ungrabstr(p) to return to the previous mode of operation.
1727  *
1728  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1729  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1730  * is space for at least one character.
1731  */
1732 static void *
1733 growstackstr(void)
1734 {
1735         size_t len = stackblocksize();
1736         growstackblock();
1737         return (char *)stackblock() + len;
1738 }
1739
1740 /*
1741  * Called from CHECKSTRSPACE.
1742  */
1743 static char *
1744 makestrspace(size_t newlen, char *p)
1745 {
1746         size_t len = p - g_stacknxt;
1747         size_t size;
1748
1749         for (;;) {
1750                 size_t nleft;
1751
1752                 size = stackblocksize();
1753                 nleft = size - len;
1754                 if (nleft >= newlen)
1755                         break;
1756                 growstackblock();
1757         }
1758         return (char *)stackblock() + len;
1759 }
1760
1761 static char *
1762 stack_nputstr(const char *s, size_t n, char *p)
1763 {
1764         p = makestrspace(n, p);
1765         p = (char *)mempcpy(p, s, n);
1766         return p;
1767 }
1768
1769 static char *
1770 stack_putstr(const char *s, char *p)
1771 {
1772         return stack_nputstr(s, strlen(s), p);
1773 }
1774
1775 static char *
1776 _STPUTC(int c, char *p)
1777 {
1778         if (p == sstrend)
1779                 p = growstackstr();
1780         *p++ = c;
1781         return p;
1782 }
1783
1784 #define STARTSTACKSTR(p)        ((p) = stackblock())
1785 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1786 #define CHECKSTRSPACE(n, p) do { \
1787         char *q = (p); \
1788         size_t l = (n); \
1789         size_t m = sstrend - q; \
1790         if (l > m) \
1791                 (p) = makestrspace(l, q); \
1792 } while (0)
1793 #define USTPUTC(c, p)           (*(p)++ = (c))
1794 #define STACKSTRNUL(p) do { \
1795         if ((p) == sstrend) \
1796                 (p) = growstackstr(); \
1797         *(p) = '\0'; \
1798 } while (0)
1799 #define STUNPUTC(p)             (--(p))
1800 #define STTOPC(p)               ((p)[-1])
1801 #define STADJUST(amount, p)     ((p) += (amount))
1802
1803 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1804 #define ungrabstackstr(s, p)    stunalloc(s)
1805 #define stackstrend()           ((void *)sstrend)
1806
1807
1808 /* ============ String helpers */
1809
1810 /*
1811  * prefix -- see if pfx is a prefix of string.
1812  */
1813 static char *
1814 prefix(const char *string, const char *pfx)
1815 {
1816         while (*pfx) {
1817                 if (*pfx++ != *string++)
1818                         return NULL;
1819         }
1820         return (char *) string;
1821 }
1822
1823 /*
1824  * Check for a valid number.  This should be elsewhere.
1825  */
1826 static int
1827 is_number(const char *p)
1828 {
1829         do {
1830                 if (!isdigit(*p))
1831                         return 0;
1832         } while (*++p != '\0');
1833         return 1;
1834 }
1835
1836 /*
1837  * Convert a string of digits to an integer, printing an error message on
1838  * failure.
1839  */
1840 static int
1841 number(const char *s)
1842 {
1843         if (!is_number(s))
1844                 ash_msg_and_raise_error(msg_illnum, s);
1845         return atoi(s);
1846 }
1847
1848 /*
1849  * Produce a single quoted string suitable as input to the shell.
1850  * The return string is allocated on the stack.
1851  */
1852 static char *
1853 single_quote(const char *s)
1854 {
1855         char *p;
1856
1857         STARTSTACKSTR(p);
1858
1859         do {
1860                 char *q;
1861                 size_t len;
1862
1863                 len = strchrnul(s, '\'') - s;
1864
1865                 q = p = makestrspace(len + 3, p);
1866
1867                 *q++ = '\'';
1868                 q = (char *)mempcpy(q, s, len);
1869                 *q++ = '\'';
1870                 s += len;
1871
1872                 STADJUST(q - p, p);
1873
1874                 if (*s != '\'')
1875                         break;
1876                 len = 0;
1877                 do len++; while (*++s == '\'');
1878
1879                 q = p = makestrspace(len + 3, p);
1880
1881                 *q++ = '"';
1882                 q = (char *)mempcpy(q, s - len, len);
1883                 *q++ = '"';
1884
1885                 STADJUST(q - p, p);
1886         } while (*s);
1887
1888         USTPUTC('\0', p);
1889
1890         return stackblock();
1891 }
1892
1893 /*
1894  * Produce a possibly single quoted string suitable as input to the shell.
1895  * If quoting was done, the return string is allocated on the stack,
1896  * otherwise a pointer to the original string is returned.
1897  */
1898 static const char *
1899 maybe_single_quote(const char *s)
1900 {
1901         const char *p = s;
1902
1903         while (*p) {
1904                 /* Assuming ACSII */
1905                 /* quote ctrl_chars space !"#$%&'()* */
1906                 if (*p < '+')
1907                         goto need_quoting;
1908                 /* quote ;<=>? */
1909                 if (*p >= ';' && *p <= '?')
1910                         goto need_quoting;
1911                 /* quote `[\ */
1912                 if (*p == '`')
1913                         goto need_quoting;
1914                 if (*p == '[')
1915                         goto need_quoting;
1916                 if (*p == '\\')
1917                         goto need_quoting;
1918                 /* quote {|}~ DEL and high bytes */
1919                 if (*p > 'z')
1920                         goto need_quoting;
1921                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1922                 /* TODO: maybe avoid quoting % */
1923                 p++;
1924         }
1925         return s;
1926
1927  need_quoting:
1928         return single_quote(s);
1929 }
1930
1931
1932 /* ============ nextopt */
1933
1934 static char **argptr;                  /* argument list for builtin commands */
1935 static char *optionarg;                /* set by nextopt (like getopt) */
1936 static char *optptr;                   /* used by nextopt */
1937
1938 /*
1939  * XXX - should get rid of. Have all builtins use getopt(3).
1940  * The library getopt must have the BSD extension static variable
1941  * "optreset", otherwise it can't be used within the shell safely.
1942  *
1943  * Standard option processing (a la getopt) for builtin routines.
1944  * The only argument that is passed to nextopt is the option string;
1945  * the other arguments are unnecessary. It returns the character,
1946  * or '\0' on end of input.
1947  */
1948 static int
1949 nextopt(const char *optstring)
1950 {
1951         char *p;
1952         const char *q;
1953         char c;
1954
1955         p = optptr;
1956         if (p == NULL || *p == '\0') {
1957                 /* We ate entire "-param", take next one */
1958                 p = *argptr;
1959                 if (p == NULL)
1960                         return '\0';
1961                 if (*p != '-')
1962                         return '\0';
1963                 if (*++p == '\0') /* just "-" ? */
1964                         return '\0';
1965                 argptr++;
1966                 if (LONE_DASH(p)) /* "--" ? */
1967                         return '\0';
1968                 /* p => next "-param" */
1969         }
1970         /* p => some option char in the middle of a "-param" */
1971         c = *p++;
1972         for (q = optstring; *q != c;) {
1973                 if (*q == '\0')
1974                         ash_msg_and_raise_error("illegal option -%c", c);
1975                 if (*++q == ':')
1976                         q++;
1977         }
1978         if (*++q == ':') {
1979                 if (*p == '\0') {
1980                         p = *argptr++;
1981                         if (p == NULL)
1982                                 ash_msg_and_raise_error("no arg for -%c option", c);
1983                 }
1984                 optionarg = p;
1985                 p = NULL;
1986         }
1987         optptr = p;
1988         return c;
1989 }
1990
1991
1992 /* ============ Shell variables */
1993
1994 struct shparam {
1995         int nparam;             /* # of positional parameters (without $0) */
1996 #if ENABLE_ASH_GETOPTS
1997         int optind;             /* next parameter to be processed by getopts */
1998         int optoff;             /* used by getopts */
1999 #endif
2000         unsigned char malloced; /* if parameter list dynamically allocated */
2001         char **p;               /* parameter list */
2002 };
2003
2004 /*
2005  * Free the list of positional parameters.
2006  */
2007 static void
2008 freeparam(volatile struct shparam *param)
2009 {
2010         if (param->malloced) {
2011                 char **ap, **ap1;
2012                 ap = ap1 = param->p;
2013                 while (*ap)
2014                         free(*ap++);
2015                 free(ap1);
2016         }
2017 }
2018
2019 #if ENABLE_ASH_GETOPTS
2020 static void FAST_FUNC getoptsreset(const char *value);
2021 #endif
2022
2023 struct var {
2024         struct var *next;               /* next entry in hash list */
2025         int flags;                      /* flags are defined above */
2026         const char *var_text;           /* name=value */
2027         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2028                                         /* the variable gets set/unset */
2029 };
2030
2031 struct localvar {
2032         struct localvar *next;          /* next local variable in list */
2033         struct var *vp;                 /* the variable that was made local */
2034         int flags;                      /* saved flags */
2035         const char *text;               /* saved text */
2036 };
2037
2038 /* flags */
2039 #define VEXPORT         0x01    /* variable is exported */
2040 #define VREADONLY       0x02    /* variable cannot be modified */
2041 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2042 #define VTEXTFIXED      0x08    /* text is statically allocated */
2043 #define VSTACK          0x10    /* text is allocated on the stack */
2044 #define VUNSET          0x20    /* the variable is not set */
2045 #define VNOFUNC         0x40    /* don't call the callback function */
2046 #define VNOSET          0x80    /* do not set variable - just readonly test */
2047 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2048 #if ENABLE_ASH_RANDOM_SUPPORT
2049 # define VDYNAMIC       0x200   /* dynamic variable */
2050 #else
2051 # define VDYNAMIC       0
2052 #endif
2053
2054
2055 /* Need to be before varinit_data[] */
2056 #if ENABLE_LOCALE_SUPPORT
2057 static void FAST_FUNC
2058 change_lc_all(const char *value)
2059 {
2060         if (value && *value != '\0')
2061                 setlocale(LC_ALL, value);
2062 }
2063 static void FAST_FUNC
2064 change_lc_ctype(const char *value)
2065 {
2066         if (value && *value != '\0')
2067                 setlocale(LC_CTYPE, value);
2068 }
2069 #endif
2070 #if ENABLE_ASH_MAIL
2071 static void chkmail(void);
2072 static void changemail(const char *var_value) FAST_FUNC;
2073 #else
2074 # define chkmail()  ((void)0)
2075 #endif
2076 static void changepath(const char *) FAST_FUNC;
2077 #if ENABLE_ASH_RANDOM_SUPPORT
2078 static void change_random(const char *) FAST_FUNC;
2079 #endif
2080 #if BASH_EPOCH_VARS
2081 static void change_seconds(const char *) FAST_FUNC;
2082 static void change_realtime(const char *) FAST_FUNC;
2083 #endif
2084
2085 static const struct {
2086         int flags;
2087         const char *var_text;
2088         void (*var_func)(const char *) FAST_FUNC;
2089 } varinit_data[] = {
2090         /*
2091          * Note: VEXPORT would not work correctly here for NOFORK applets:
2092          * some environment strings may be constant.
2093          */
2094         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2095 #if ENABLE_ASH_MAIL
2096         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2097         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2098 #endif
2099         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2100         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2101         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2102         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2103 #if ENABLE_ASH_GETOPTS
2104         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2105 #endif
2106         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2107 #if ENABLE_ASH_RANDOM_SUPPORT
2108         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2109 #endif
2110 #if BASH_EPOCH_VARS
2111         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2112         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2113 #endif
2114 #if ENABLE_LOCALE_SUPPORT
2115         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2116         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2117 #endif
2118 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2119         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2120 #endif
2121 };
2122
2123 struct redirtab;
2124
2125 struct globals_var {
2126         struct shparam shellparam;      /* $@ current positional parameters */
2127         struct redirtab *redirlist;
2128         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2129         struct var *vartab[VTABSIZE];
2130         struct var varinit[ARRAY_SIZE(varinit_data)];
2131         int lineno;
2132         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2133 };
2134 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2135 #define G_var (*ash_ptr_to_globals_var)
2136 #define shellparam    (G_var.shellparam   )
2137 //#define redirlist     (G_var.redirlist    )
2138 #define preverrout_fd (G_var.preverrout_fd)
2139 #define vartab        (G_var.vartab       )
2140 #define varinit       (G_var.varinit      )
2141 #define lineno        (G_var.lineno       )
2142 #define linenovar     (G_var.linenovar    )
2143 #define vifs      varinit[0]
2144 #if ENABLE_ASH_MAIL
2145 # define vmail    varinit[1]
2146 # define vmpath   varinit[2]
2147 #endif
2148 #define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2149 #define vpath     varinit[VAR_OFFSET1 + 1]
2150 #define vps1      varinit[VAR_OFFSET1 + 2]
2151 #define vps2      varinit[VAR_OFFSET1 + 3]
2152 #define vps4      varinit[VAR_OFFSET1 + 4]
2153 #if ENABLE_ASH_GETOPTS
2154 # define voptind  varinit[VAR_OFFSET1 + 5]
2155 #endif
2156 #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2157 #define vlineno   varinit[VAR_OFFSET2 + 5]
2158 #if ENABLE_ASH_RANDOM_SUPPORT
2159 # define vrandom  varinit[VAR_OFFSET2 + 6]
2160 #endif
2161 #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2162 #if BASH_EPOCH_VARS
2163 # define vepochs  varinit[VAR_OFFSET3 + 6]
2164 # define vepochr  varinit[VAR_OFFSET3 + 7]
2165 #endif
2166 #define INIT_G_var() do { \
2167         unsigned i; \
2168         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2169         barrier(); \
2170         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2171                 varinit[i].flags    = varinit_data[i].flags; \
2172                 varinit[i].var_text = varinit_data[i].var_text; \
2173                 varinit[i].var_func = varinit_data[i].var_func; \
2174         } \
2175         strcpy(linenovar, "LINENO="); \
2176         vlineno.var_text = linenovar; \
2177 } while (0)
2178
2179 /*
2180  * The following macros access the values of the above variables.
2181  * They have to skip over the name.  They return the null string
2182  * for unset variables.
2183  */
2184 #define ifsval()        (vifs.var_text + 4)
2185 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2186 #if ENABLE_ASH_MAIL
2187 # define mailval()      (vmail.var_text + 5)
2188 # define mpathval()     (vmpath.var_text + 9)
2189 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2190 #endif
2191 #define pathval()       (vpath.var_text + 5)
2192 #define ps1val()        (vps1.var_text + 4)
2193 #define ps2val()        (vps2.var_text + 4)
2194 #define ps4val()        (vps4.var_text + 4)
2195 #if ENABLE_ASH_GETOPTS
2196 # define optindval()    (voptind.var_text + 7)
2197 #endif
2198
2199 #if ENABLE_ASH_GETOPTS
2200 static void FAST_FUNC
2201 getoptsreset(const char *value)
2202 {
2203         shellparam.optind = 1;
2204         if (is_number(value))
2205                 shellparam.optind = number(value) ?: 1;
2206         shellparam.optoff = -1;
2207 }
2208 #endif
2209
2210 /*
2211  * Compares two strings up to the first = or '\0'.  The first
2212  * string must be terminated by '='; the second may be terminated by
2213  * either '=' or '\0'.
2214  */
2215 static int
2216 varcmp(const char *p, const char *q)
2217 {
2218         int c, d;
2219
2220         while ((c = *p) == (d = *q)) {
2221                 if (c == '\0' || c == '=')
2222                         goto out;
2223                 p++;
2224                 q++;
2225         }
2226         if (c == '=')
2227                 c = '\0';
2228         if (d == '=')
2229                 d = '\0';
2230  out:
2231         return c - d;
2232 }
2233
2234 /*
2235  * Find the appropriate entry in the hash table from the name.
2236  */
2237 static struct var **
2238 hashvar(const char *p)
2239 {
2240         unsigned hashval;
2241
2242         hashval = ((unsigned char) *p) << 4;
2243         while (*p && *p != '=')
2244                 hashval += (unsigned char) *p++;
2245         return &vartab[hashval % VTABSIZE];
2246 }
2247
2248 static int
2249 vpcmp(const void *a, const void *b)
2250 {
2251         return varcmp(*(const char **)a, *(const char **)b);
2252 }
2253
2254 /*
2255  * This routine initializes the builtin variables.
2256  */
2257 static void
2258 initvar(void)
2259 {
2260         struct var *vp;
2261         struct var *end;
2262         struct var **vpp;
2263
2264         /*
2265          * PS1 depends on uid
2266          */
2267 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2268         vps1.var_text = "PS1=\\w \\$ ";
2269 #else
2270         if (!geteuid())
2271                 vps1.var_text = "PS1=# ";
2272 #endif
2273         vp = varinit;
2274         end = vp + ARRAY_SIZE(varinit);
2275         do {
2276                 vpp = hashvar(vp->var_text);
2277                 vp->next = *vpp;
2278                 *vpp = vp;
2279         } while (++vp < end);
2280 }
2281
2282 static struct var **
2283 findvar(struct var **vpp, const char *name)
2284 {
2285         for (; *vpp; vpp = &(*vpp)->next) {
2286                 if (varcmp((*vpp)->var_text, name) == 0) {
2287                         break;
2288                 }
2289         }
2290         return vpp;
2291 }
2292
2293 /*
2294  * Find the value of a variable.  Returns NULL if not set.
2295  */
2296 static const char* FAST_FUNC
2297 lookupvar(const char *name)
2298 {
2299         struct var *v;
2300
2301         v = *findvar(hashvar(name), name);
2302         if (v) {
2303 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2304         /*
2305          * Dynamic variables are implemented roughly the same way they are
2306          * in bash. Namely, they're "special" so long as they aren't unset.
2307          * As soon as they're unset, they're no longer dynamic, and dynamic
2308          * lookup will no longer happen at that point. -- PFM.
2309          */
2310                 if (v->flags & VDYNAMIC)
2311                         v->var_func(NULL);
2312 #endif
2313                 if (!(v->flags & VUNSET)) {
2314                         if (v == &vlineno && v->var_text == linenovar) {
2315                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2316                         }
2317                         return var_end(v->var_text);
2318                 }
2319         }
2320         return NULL;
2321 }
2322
2323 #if ENABLE_UNICODE_SUPPORT
2324 static void
2325 reinit_unicode_for_ash(void)
2326 {
2327         /* Unicode support should be activated even if LANG is set
2328          * _during_ shell execution, not only if it was set when
2329          * shell was started. Therefore, re-check LANG every time:
2330          */
2331         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2332          || ENABLE_UNICODE_USING_LOCALE
2333         ) {
2334                 const char *s = lookupvar("LC_ALL");
2335                 if (!s) s = lookupvar("LC_CTYPE");
2336                 if (!s) s = lookupvar("LANG");
2337                 reinit_unicode(s);
2338         }
2339 }
2340 #else
2341 # define reinit_unicode_for_ash() ((void)0)
2342 #endif
2343
2344 /*
2345  * Search the environment of a builtin command.
2346  */
2347 static ALWAYS_INLINE const char *
2348 bltinlookup(const char *name)
2349 {
2350         return lookupvar(name);
2351 }
2352
2353 /*
2354  * Same as setvar except that the variable and value are passed in
2355  * the first argument as name=value.  Since the first argument will
2356  * be actually stored in the table, it should not be a string that
2357  * will go away.
2358  * Called with interrupts off.
2359  */
2360 static struct var *
2361 setvareq(char *s, int flags)
2362 {
2363         struct var *vp, **vpp;
2364
2365         vpp = hashvar(s);
2366         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2367         vpp = findvar(vpp, s);
2368         vp = *vpp;
2369         if (vp) {
2370                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2371                         const char *n;
2372
2373                         if (flags & VNOSAVE)
2374                                 free(s);
2375                         n = vp->var_text;
2376                         exitstatus = 1;
2377                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2378                 }
2379
2380                 if (flags & VNOSET)
2381                         goto out;
2382
2383                 if (vp->var_func && !(flags & VNOFUNC))
2384                         vp->var_func(var_end(s));
2385
2386                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2387                         free((char*)vp->var_text);
2388
2389                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2390                         *vpp = vp->next;
2391                         free(vp);
2392  out_free:
2393                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2394                                 free(s);
2395                         goto out;
2396                 }
2397
2398                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2399 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2400                 if (flags & VUNSET)
2401                         flags &= ~VDYNAMIC;
2402 #endif
2403         } else {
2404                 /* variable s is not found */
2405                 if (flags & VNOSET)
2406                         goto out;
2407                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2408                         goto out_free;
2409                 vp = ckzalloc(sizeof(*vp));
2410                 vp->next = *vpp;
2411                 /*vp->func = NULL; - ckzalloc did it */
2412                 *vpp = vp;
2413         }
2414         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2415                 s = ckstrdup(s);
2416         vp->var_text = s;
2417         vp->flags = flags;
2418
2419  out:
2420         return vp;
2421 }
2422
2423 /*
2424  * Set the value of a variable.  The flags argument is ored with the
2425  * flags of the variable.  If val is NULL, the variable is unset.
2426  */
2427 static struct var *
2428 setvar(const char *name, const char *val, int flags)
2429 {
2430         const char *q;
2431         char *p;
2432         char *nameeq;
2433         size_t namelen;
2434         size_t vallen;
2435         struct var *vp;
2436
2437         q = endofname(name);
2438         p = strchrnul(q, '=');
2439         namelen = p - name;
2440         if (!namelen || p != q)
2441                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2442         vallen = 0;
2443         if (val == NULL) {
2444                 flags |= VUNSET;
2445         } else {
2446                 vallen = strlen(val);
2447         }
2448
2449         INT_OFF;
2450         nameeq = ckzalloc(namelen + vallen + 2);
2451         p = mempcpy(nameeq, name, namelen);
2452         if (val) {
2453                 *p++ = '=';
2454                 memcpy(p, val, vallen);
2455         }
2456         vp = setvareq(nameeq, flags | VNOSAVE);
2457         INT_ON;
2458
2459         return vp;
2460 }
2461
2462 static void FAST_FUNC
2463 setvar0(const char *name, const char *val)
2464 {
2465         setvar(name, val, 0);
2466 }
2467
2468 /*
2469  * Unset the specified variable.
2470  */
2471 static void
2472 unsetvar(const char *s)
2473 {
2474         setvar(s, NULL, 0);
2475 }
2476
2477 /*
2478  * Process a linked list of variable assignments.
2479  */
2480 static void
2481 listsetvar(struct strlist *list_set_var, int flags)
2482 {
2483         struct strlist *lp = list_set_var;
2484
2485         if (!lp)
2486                 return;
2487         INT_OFF;
2488         do {
2489                 setvareq(lp->text, flags);
2490                 lp = lp->next;
2491         } while (lp);
2492         INT_ON;
2493 }
2494
2495 /*
2496  * Generate a list of variables satisfying the given conditions.
2497  */
2498 #if !ENABLE_FEATURE_SH_NOFORK
2499 # define listvars(on, off, lp, end) listvars(on, off, end)
2500 #endif
2501 static char **
2502 listvars(int on, int off, struct strlist *lp, char ***end)
2503 {
2504         struct var **vpp;
2505         struct var *vp;
2506         char **ep;
2507         int mask;
2508
2509         STARTSTACKSTR(ep);
2510         vpp = vartab;
2511         mask = on | off;
2512         do {
2513                 for (vp = *vpp; vp; vp = vp->next) {
2514                         if ((vp->flags & mask) == on) {
2515 #if ENABLE_FEATURE_SH_NOFORK
2516                                 /* If variable with the same name is both
2517                                  * exported and temporarily set for a command:
2518                                  *  export ZVAR=5
2519                                  *  ZVAR=6 printenv
2520                                  * then "ZVAR=6" will be both in vartab and
2521                                  * lp lists. Do not pass it twice to printenv.
2522                                  */
2523                                 struct strlist *lp1 = lp;
2524                                 while (lp1) {
2525                                         if (strcmp(lp1->text, vp->var_text) == 0)
2526                                                 goto skip;
2527                                         lp1 = lp1->next;
2528                                 }
2529 #endif
2530                                 if (ep == stackstrend())
2531                                         ep = growstackstr();
2532                                 *ep++ = (char*)vp->var_text;
2533 #if ENABLE_FEATURE_SH_NOFORK
2534  skip: ;
2535 #endif
2536                         }
2537                 }
2538         } while (++vpp < vartab + VTABSIZE);
2539
2540 #if ENABLE_FEATURE_SH_NOFORK
2541         while (lp) {
2542                 if (ep == stackstrend())
2543                         ep = growstackstr();
2544                 *ep++ = lp->text;
2545                 lp = lp->next;
2546         }
2547 #endif
2548
2549         if (ep == stackstrend())
2550                 ep = growstackstr();
2551         if (end)
2552                 *end = ep;
2553         *ep++ = NULL;
2554         return grabstackstr(ep);
2555 }
2556
2557
2558 /* ============ Path search helper
2559  *
2560  * The variable path (passed by reference) should be set to the start
2561  * of the path before the first call; path_advance will update
2562  * this value as it proceeds.  Successive calls to path_advance will return
2563  * the possible path expansions in sequence.  If an option (indicated by
2564  * a percent sign) appears in the path entry then the global variable
2565  * pathopt will be set to point to it; otherwise pathopt will be set to
2566  * NULL.
2567  */
2568 static const char *pathopt;     /* set by path_advance */
2569
2570 static char *
2571 path_advance(const char **path, const char *name)
2572 {
2573         const char *p;
2574         char *q;
2575         const char *start;
2576         size_t len;
2577
2578         if (*path == NULL)
2579                 return NULL;
2580         start = *path;
2581         for (p = start; *p && *p != ':' && *p != '%'; p++)
2582                 continue;
2583         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2584         while (stackblocksize() < len)
2585                 growstackblock();
2586         q = stackblock();
2587         if (p != start) {
2588                 q = mempcpy(q, start, p - start);
2589                 *q++ = '/';
2590         }
2591         strcpy(q, name);
2592         pathopt = NULL;
2593         if (*p == '%') {
2594                 pathopt = ++p;
2595                 while (*p && *p != ':')
2596                         p++;
2597         }
2598         if (*p == ':')
2599                 *path = p + 1;
2600         else
2601                 *path = NULL;
2602         return stalloc(len);
2603 }
2604
2605
2606 /* ============ Prompt */
2607
2608 static smallint doprompt;                   /* if set, prompt the user */
2609 static smallint needprompt;                 /* true if interactive and at start of line */
2610
2611 #if ENABLE_FEATURE_EDITING
2612 static line_input_t *line_input_state;
2613 static const char *cmdedit_prompt;
2614 static void
2615 putprompt(const char *s)
2616 {
2617         if (ENABLE_ASH_EXPAND_PRMT) {
2618                 free((char*)cmdedit_prompt);
2619                 cmdedit_prompt = ckstrdup(s);
2620                 return;
2621         }
2622         cmdedit_prompt = s;
2623 }
2624 #else
2625 static void
2626 putprompt(const char *s)
2627 {
2628         out2str(s);
2629 }
2630 #endif
2631
2632 /* expandstr() needs parsing machinery, so it is far away ahead... */
2633 static const char *expandstr(const char *ps, int syntax_type);
2634 /* Values for syntax param */
2635 #define BASESYNTAX 0    /* not in quotes */
2636 #define DQSYNTAX   1    /* in double quotes */
2637 #define SQSYNTAX   2    /* in single quotes */
2638 #define ARISYNTAX  3    /* in arithmetic */
2639 #if ENABLE_ASH_EXPAND_PRMT
2640 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2641 #endif
2642 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2643
2644 /*
2645  * called by editline -- any expansions to the prompt should be added here.
2646  */
2647 static void
2648 setprompt_if(smallint do_set, int whichprompt)
2649 {
2650         const char *prompt;
2651         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2652
2653         if (!do_set)
2654                 return;
2655
2656         needprompt = 0;
2657
2658         switch (whichprompt) {
2659         case 1:
2660                 prompt = ps1val();
2661                 break;
2662         case 2:
2663                 prompt = ps2val();
2664                 break;
2665         default:                        /* 0 */
2666                 prompt = nullstr;
2667         }
2668 #if ENABLE_ASH_EXPAND_PRMT
2669         pushstackmark(&smark, stackblocksize());
2670         putprompt(expandstr(prompt, PSSYNTAX));
2671         popstackmark(&smark);
2672 #else
2673         putprompt(prompt);
2674 #endif
2675 }
2676
2677
2678 /* ============ The cd and pwd commands */
2679
2680 #define CD_PHYSICAL 1
2681 #define CD_PRINT 2
2682
2683 static int
2684 cdopt(void)
2685 {
2686         int flags = 0;
2687         int i, j;
2688
2689         j = 'L';
2690         while ((i = nextopt("LP")) != '\0') {
2691                 if (i != j) {
2692                         flags ^= CD_PHYSICAL;
2693                         j = i;
2694                 }
2695         }
2696
2697         return flags;
2698 }
2699
2700 /*
2701  * Update curdir (the name of the current directory) in response to a
2702  * cd command.
2703  */
2704 static const char *
2705 updatepwd(const char *dir)
2706 {
2707         char *new;
2708         char *p;
2709         char *cdcomppath;
2710         const char *lim;
2711
2712         cdcomppath = sstrdup(dir);
2713         STARTSTACKSTR(new);
2714         if (*dir != '/') {
2715                 if (curdir == nullstr)
2716                         return 0;
2717                 new = stack_putstr(curdir, new);
2718         }
2719         new = makestrspace(strlen(dir) + 2, new);
2720         lim = (char *)stackblock() + 1;
2721         if (*dir != '/') {
2722                 if (new[-1] != '/')
2723                         USTPUTC('/', new);
2724                 if (new > lim && *lim == '/')
2725                         lim++;
2726         } else {
2727                 USTPUTC('/', new);
2728                 cdcomppath++;
2729                 if (dir[1] == '/' && dir[2] != '/') {
2730                         USTPUTC('/', new);
2731                         cdcomppath++;
2732                         lim++;
2733                 }
2734         }
2735         p = strtok(cdcomppath, "/");
2736         while (p) {
2737                 switch (*p) {
2738                 case '.':
2739                         if (p[1] == '.' && p[2] == '\0') {
2740                                 while (new > lim) {
2741                                         STUNPUTC(new);
2742                                         if (new[-1] == '/')
2743                                                 break;
2744                                 }
2745                                 break;
2746                         }
2747                         if (p[1] == '\0')
2748                                 break;
2749                         /* fall through */
2750                 default:
2751                         new = stack_putstr(p, new);
2752                         USTPUTC('/', new);
2753                 }
2754                 p = strtok(NULL, "/");
2755         }
2756         if (new > lim)
2757                 STUNPUTC(new);
2758         *new = 0;
2759         return stackblock();
2760 }
2761
2762 /*
2763  * Find out what the current directory is. If we already know the current
2764  * directory, this routine returns immediately.
2765  */
2766 static char *
2767 getpwd(void)
2768 {
2769         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2770         return dir ? dir : nullstr;
2771 }
2772
2773 static void
2774 setpwd(const char *val, int setold)
2775 {
2776         char *oldcur, *dir;
2777
2778         oldcur = dir = curdir;
2779
2780         if (setold) {
2781                 setvar("OLDPWD", oldcur, VEXPORT);
2782         }
2783         INT_OFF;
2784         if (physdir != nullstr) {
2785                 if (physdir != oldcur)
2786                         free(physdir);
2787                 physdir = nullstr;
2788         }
2789         if (oldcur == val || !val) {
2790                 char *s = getpwd();
2791                 physdir = s;
2792                 if (!val)
2793                         dir = s;
2794         } else
2795                 dir = ckstrdup(val);
2796         if (oldcur != dir && oldcur != nullstr) {
2797                 free(oldcur);
2798         }
2799         curdir = dir;
2800         INT_ON;
2801         setvar("PWD", dir, VEXPORT);
2802 }
2803
2804 static void hashcd(void);
2805
2806 /*
2807  * Actually do the chdir.  We also call hashcd to let other routines
2808  * know that the current directory has changed.
2809  */
2810 static int
2811 docd(const char *dest, int flags)
2812 {
2813         const char *dir = NULL;
2814         int err;
2815
2816         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2817
2818         INT_OFF;
2819         if (!(flags & CD_PHYSICAL)) {
2820                 dir = updatepwd(dest);
2821                 if (dir)
2822                         dest = dir;
2823         }
2824         err = chdir(dest);
2825         if (err)
2826                 goto out;
2827         setpwd(dir, 1);
2828         hashcd();
2829  out:
2830         INT_ON;
2831         return err;
2832 }
2833
2834 static int FAST_FUNC
2835 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2836 {
2837         const char *dest;
2838         const char *path;
2839         const char *p;
2840         char c;
2841         struct stat statb;
2842         int flags;
2843
2844         flags = cdopt();
2845         dest = *argptr;
2846         if (!dest)
2847                 dest = bltinlookup("HOME");
2848         else if (LONE_DASH(dest)) {
2849                 dest = bltinlookup("OLDPWD");
2850                 flags |= CD_PRINT;
2851         }
2852         if (!dest)
2853                 dest = nullstr;
2854         if (*dest == '/')
2855                 goto step6;
2856         if (*dest == '.') {
2857                 c = dest[1];
2858  dotdot:
2859                 switch (c) {
2860                 case '\0':
2861                 case '/':
2862                         goto step6;
2863                 case '.':
2864                         c = dest[2];
2865                         if (c != '.')
2866                                 goto dotdot;
2867                 }
2868         }
2869         if (!*dest)
2870                 dest = ".";
2871         path = bltinlookup("CDPATH");
2872         while (path) {
2873                 c = *path;
2874                 p = path_advance(&path, dest);
2875                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2876                         if (c && c != ':')
2877                                 flags |= CD_PRINT;
2878  docd:
2879                         if (!docd(p, flags))
2880                                 goto out;
2881                         goto err;
2882                 }
2883         }
2884
2885  step6:
2886         p = dest;
2887         goto docd;
2888
2889  err:
2890         ash_msg_and_raise_perror("can't cd to %s", dest);
2891         /* NOTREACHED */
2892  out:
2893         if (flags & CD_PRINT)
2894                 out1fmt("%s\n", curdir);
2895         return 0;
2896 }
2897
2898 static int FAST_FUNC
2899 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2900 {
2901         int flags;
2902         const char *dir = curdir;
2903
2904         flags = cdopt();
2905         if (flags) {
2906                 if (physdir == nullstr)
2907                         setpwd(dir, 0);
2908                 dir = physdir;
2909         }
2910         out1fmt("%s\n", dir);
2911         return 0;
2912 }
2913
2914
2915 /* ============ ... */
2916
2917
2918 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2919
2920 /* Syntax classes */
2921 #define CWORD     0             /* character is nothing special */
2922 #define CNL       1             /* newline character */
2923 #define CBACK     2             /* a backslash character */
2924 #define CSQUOTE   3             /* single quote */
2925 #define CDQUOTE   4             /* double quote */
2926 #define CENDQUOTE 5             /* a terminating quote */
2927 #define CBQUOTE   6             /* backwards single quote */
2928 #define CVAR      7             /* a dollar sign */
2929 #define CENDVAR   8             /* a '}' character */
2930 #define CLP       9             /* a left paren in arithmetic */
2931 #define CRP      10             /* a right paren in arithmetic */
2932 #define CENDFILE 11             /* end of file */
2933 #define CCTL     12             /* like CWORD, except it must be escaped */
2934 #define CSPCL    13             /* these terminate a word */
2935 #define CIGN     14             /* character should be ignored */
2936
2937 #define PEOF     256
2938 #if ENABLE_ASH_ALIAS
2939 # define PEOA    257
2940 #endif
2941
2942 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2943
2944 #if ENABLE_FEATURE_SH_MATH
2945 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2946 #else
2947 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2948 #endif
2949 static const uint16_t S_I_T[] ALIGN2 = {
2950 #if ENABLE_ASH_ALIAS
2951         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2952 #endif
2953         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2954         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2955         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2956         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2957         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2958         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2959         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2960         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2961         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2962         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2963         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2964 #if !USE_SIT_FUNCTION
2965         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2966         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2967         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2968 #endif
2969 #undef SIT_ITEM
2970 };
2971 /* Constants below must match table above */
2972 enum {
2973 #if ENABLE_ASH_ALIAS
2974         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2975 #endif
2976         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2977         CNL_CNL_CNL_CNL                    , /*  2 */
2978         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2979         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2980         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2981         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2982         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2983         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2984         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2985         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2986         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2987         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2988         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2989         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2990 };
2991
2992 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2993  * caller must ensure proper cast on it if c is *char_ptr!
2994  */
2995 #if USE_SIT_FUNCTION
2996
2997 static int
2998 SIT(int c, int syntax)
2999 {
3000         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3001         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3002         /*
3003          * This causes '/' to be prepended with CTLESC in dquoted string,
3004          * making "./file"* treated incorrectly because we feed
3005          * ".\/file*" string to glob(), confusing it (see expandmeta func).
3006          * The "homegrown" glob implementation is okay with that,
3007          * but glibc one isn't. With '/' always treated as CWORD,
3008          * both work fine.
3009          */
3010 # if ENABLE_ASH_ALIAS
3011         static const uint8_t syntax_index_table[] ALIGN1 = {
3012                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
3013                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
3014                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
3015                 11, 3                           /* "}~" */
3016         };
3017 # else
3018         static const uint8_t syntax_index_table[] ALIGN1 = {
3019                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3020                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3021                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3022                 10, 2                           /* "}~" */
3023         };
3024 # endif
3025         const char *s;
3026         int indx;
3027
3028         if (c == PEOF)
3029                 return CENDFILE;
3030 # if ENABLE_ASH_ALIAS
3031         if (c == PEOA)
3032                 indx = 0;
3033         else
3034 # endif
3035         {
3036                 /* Cast is purely for paranoia here,
3037                  * just in case someone passed signed char to us */
3038                 if ((unsigned char)c >= CTL_FIRST
3039                  && (unsigned char)c <= CTL_LAST
3040                 ) {
3041                         return CCTL;
3042                 }
3043                 s = strchrnul(spec_symbls, c);
3044                 if (*s == '\0')
3045                         return CWORD;
3046                 indx = syntax_index_table[s - spec_symbls];
3047         }
3048         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3049 }
3050
3051 #else   /* !USE_SIT_FUNCTION */
3052
3053 static const uint8_t syntax_index_table[] ALIGN1 = {
3054         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3055         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3056         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3057         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3058         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3059         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3060         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3061         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3062         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3063         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3064         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3065         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3066         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3067         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3068         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3069         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3070         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3071         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3072         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3073         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3074         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3075         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3076         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3077         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3078         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3079         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3080         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3081         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3082         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3083         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3084         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3085         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3086         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3087         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3088         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3089         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3090         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3092         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3094         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3095         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3096         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3097         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3098         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3100         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3101         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3102 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3103         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3104         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3105         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3106         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3107         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3108         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3109         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3112         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3115         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3116         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3117         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3118         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3119         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3120         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3121         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3122         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3123         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3124         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3125         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3126         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3127         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3128         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3129         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3130         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3131         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3132         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3133         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3134         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3135         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3136         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3137         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3138         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3139         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3140         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3141         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3142         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3143         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3144         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3145         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3146         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3147         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3148         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3149         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3150         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3151         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3152         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3153         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3154         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3155         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3156         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3157         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3158         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3159         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3160         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3161         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3162         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3163         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3164         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3165         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3166         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3167         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3168         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3169         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3170         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3171         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3172         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3173         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3174         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3175         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3176         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3177         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3178         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3179         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3180         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3181         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3182         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3183         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3184         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3185         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3186         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3187         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3188         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3189         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3190         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3191         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3192         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3193         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3271         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3272         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3273         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3274         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3275         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3276         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3277         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3278         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3279         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3280         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3281         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3282         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3283         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3284         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3285         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3286         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3287         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3288         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3289         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3290         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3291         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3292         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3293         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3294         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3295         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3296         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3297         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3298         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3299         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3300         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3301         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3302         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3303         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3304         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3305         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3306         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3307         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3308         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3309         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3310         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3311         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3312         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3313 # if ENABLE_ASH_ALIAS
3314         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3315 # endif
3316 };
3317
3318 #if 1
3319 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3320 #else /* debug version, caught one signed char bug */
3321 # define SIT(c, syntax) \
3322         ({ \
3323                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3324                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3325                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3326                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3327                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3328         })
3329 #endif
3330
3331 #endif  /* !USE_SIT_FUNCTION */
3332
3333
3334 /* ============ Alias handling */
3335
3336 #if ENABLE_ASH_ALIAS
3337
3338 #define ALIASINUSE 1
3339 #define ALIASDEAD  2
3340
3341 struct alias {
3342         struct alias *next;
3343         char *name;
3344         char *val;
3345         int flag;
3346 };
3347
3348
3349 static struct alias **atab; // [ATABSIZE];
3350 #define INIT_G_alias() do { \
3351         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3352 } while (0)
3353
3354
3355 static struct alias **
3356 __lookupalias(const char *name)
3357 {
3358         unsigned int hashval;
3359         struct alias **app;
3360         const char *p;
3361         unsigned int ch;
3362
3363         p = name;
3364
3365         ch = (unsigned char)*p;
3366         hashval = ch << 4;
3367         while (ch) {
3368                 hashval += ch;
3369                 ch = (unsigned char)*++p;
3370         }
3371         app = &atab[hashval % ATABSIZE];
3372
3373         for (; *app; app = &(*app)->next) {
3374                 if (strcmp(name, (*app)->name) == 0) {
3375                         break;
3376                 }
3377         }
3378
3379         return app;
3380 }
3381
3382 static struct alias *
3383 lookupalias(const char *name, int check)
3384 {
3385         struct alias *ap = *__lookupalias(name);
3386
3387         if (check && ap && (ap->flag & ALIASINUSE))
3388                 return NULL;
3389         return ap;
3390 }
3391
3392 static struct alias *
3393 freealias(struct alias *ap)
3394 {
3395         struct alias *next;
3396
3397         if (ap->flag & ALIASINUSE) {
3398                 ap->flag |= ALIASDEAD;
3399                 return ap;
3400         }
3401
3402         next = ap->next;
3403         free(ap->name);
3404         free(ap->val);
3405         free(ap);
3406         return next;
3407 }
3408
3409 static void
3410 setalias(const char *name, const char *val)
3411 {
3412         struct alias *ap, **app;
3413
3414         app = __lookupalias(name);
3415         ap = *app;
3416         INT_OFF;
3417         if (ap) {
3418                 if (!(ap->flag & ALIASINUSE)) {
3419                         free(ap->val);
3420                 }
3421                 ap->val = ckstrdup(val);
3422                 ap->flag &= ~ALIASDEAD;
3423         } else {
3424                 /* not found */
3425                 ap = ckzalloc(sizeof(struct alias));
3426                 ap->name = ckstrdup(name);
3427                 ap->val = ckstrdup(val);
3428                 /*ap->flag = 0; - ckzalloc did it */
3429                 /*ap->next = NULL;*/
3430                 *app = ap;
3431         }
3432         INT_ON;
3433 }
3434
3435 static int
3436 unalias(const char *name)
3437 {
3438         struct alias **app;
3439
3440         app = __lookupalias(name);
3441
3442         if (*app) {
3443                 INT_OFF;
3444                 *app = freealias(*app);
3445                 INT_ON;
3446                 return 0;
3447         }
3448
3449         return 1;
3450 }
3451
3452 static void
3453 rmaliases(void)
3454 {
3455         struct alias *ap, **app;
3456         int i;
3457
3458         INT_OFF;
3459         for (i = 0; i < ATABSIZE; i++) {
3460                 app = &atab[i];
3461                 for (ap = *app; ap; ap = *app) {
3462                         *app = freealias(*app);
3463                         if (ap == *app) {
3464                                 app = &ap->next;
3465                         }
3466                 }
3467         }
3468         INT_ON;
3469 }
3470
3471 static void
3472 printalias(const struct alias *ap)
3473 {
3474         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3475 }
3476
3477 /*
3478  * TODO - sort output
3479  */
3480 static int FAST_FUNC
3481 aliascmd(int argc UNUSED_PARAM, char **argv)
3482 {
3483         char *n, *v;
3484         int ret = 0;
3485         struct alias *ap;
3486
3487         if (!argv[1]) {
3488                 int i;
3489
3490                 for (i = 0; i < ATABSIZE; i++) {
3491                         for (ap = atab[i]; ap; ap = ap->next) {
3492                                 printalias(ap);
3493                         }
3494                 }
3495                 return 0;
3496         }
3497         while ((n = *++argv) != NULL) {
3498                 v = strchr(n+1, '=');
3499                 if (v == NULL) { /* n+1: funny ksh stuff */
3500                         ap = *__lookupalias(n);
3501                         if (ap == NULL) {
3502                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3503                                 ret = 1;
3504                         } else
3505                                 printalias(ap);
3506                 } else {
3507                         *v++ = '\0';
3508                         setalias(n, v);
3509                 }
3510         }
3511
3512         return ret;
3513 }
3514
3515 static int FAST_FUNC
3516 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3517 {
3518         int i;
3519
3520         while (nextopt("a") != '\0') {
3521                 rmaliases();
3522                 return 0;
3523         }
3524         for (i = 0; *argptr; argptr++) {
3525                 if (unalias(*argptr)) {
3526                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3527                         i = 1;
3528                 }
3529         }
3530
3531         return i;
3532 }
3533
3534 #endif /* ASH_ALIAS */
3535
3536
3537 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3538 #define FORK_FG    0
3539 #define FORK_BG    1
3540 #define FORK_NOJOB 2
3541
3542 /* mode flags for showjob(s) */
3543 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3544 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3545 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3546 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3547
3548 /*
3549  * A job structure contains information about a job.  A job is either a
3550  * single process or a set of processes contained in a pipeline.  In the
3551  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3552  * array of pids.
3553  */
3554 struct procstat {
3555         pid_t   ps_pid;         /* process id */
3556         int     ps_status;      /* last process status from wait() */
3557         char    *ps_cmd;        /* text of command being run */
3558 };
3559
3560 struct job {
3561         struct procstat ps0;    /* status of process */
3562         struct procstat *ps;    /* status of processes when more than one */
3563 #if JOBS
3564         int stopstatus;         /* status of a stopped job */
3565 #endif
3566         unsigned nprocs;        /* number of processes */
3567
3568 #define JOBRUNNING      0       /* at least one proc running */
3569 #define JOBSTOPPED      1       /* all procs are stopped */
3570 #define JOBDONE         2       /* all procs are completed */
3571         unsigned
3572                 state: 8,
3573 #if JOBS
3574                 sigint: 1,      /* job was killed by SIGINT */
3575                 jobctl: 1,      /* job running under job control */
3576 #endif
3577                 waited: 1,      /* true if this entry has been waited for */
3578                 used: 1,        /* true if this entry is in used */
3579                 changed: 1;     /* true if status has changed */
3580         struct job *prev_job;   /* previous job */
3581 };
3582
3583 static struct job *makejob(/*union node *,*/ int);
3584 static int forkshell(struct job *, union node *, int);
3585 static int waitforjob(struct job *);
3586
3587 #if !JOBS
3588 enum { doing_jobctl = 0 };
3589 #define setjobctl(on) do {} while (0)
3590 #else
3591 static smallint doing_jobctl; //references:8
3592 static void setjobctl(int);
3593 #endif
3594
3595 /*
3596  * Ignore a signal.
3597  */
3598 static void
3599 ignoresig(int signo)
3600 {
3601         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3602         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3603                 /* No, need to do it */
3604                 signal(signo, SIG_IGN);
3605         }
3606         sigmode[signo - 1] = S_HARD_IGN;
3607 }
3608
3609 /*
3610  * Only one usage site - in setsignal()
3611  */
3612 static void
3613 signal_handler(int signo)
3614 {
3615         if (signo == SIGCHLD) {
3616                 got_sigchld = 1;
3617                 if (!trap[SIGCHLD])
3618                         return;
3619         }
3620
3621         gotsig[signo - 1] = 1;
3622         pending_sig = signo;
3623
3624         if (signo == SIGINT && !trap[SIGINT]) {
3625                 if (!suppress_int) {
3626                         pending_sig = 0;
3627                         raise_interrupt(); /* does not return */
3628                 }
3629                 pending_int = 1;
3630         }
3631 }
3632
3633 /*
3634  * Set the signal handler for the specified signal.  The routine figures
3635  * out what it should be set to.
3636  */
3637 static void
3638 setsignal(int signo)
3639 {
3640         char *t;
3641         char cur_act, new_act;
3642         struct sigaction act;
3643
3644         t = trap[signo];
3645         new_act = S_DFL;
3646         if (t != NULL) { /* trap for this sig is set */
3647                 new_act = S_CATCH;
3648                 if (t[0] == '\0') /* trap is "": ignore this sig */
3649                         new_act = S_IGN;
3650         }
3651
3652         if (rootshell && new_act == S_DFL) {
3653                 switch (signo) {
3654                 case SIGINT:
3655                         if (iflag || minusc || sflag == 0)
3656                                 new_act = S_CATCH;
3657                         break;
3658                 case SIGQUIT:
3659 #if DEBUG
3660                         if (debug)
3661                                 break;
3662 #endif
3663                         /* man bash:
3664                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3665                          * commands run by bash have signal handlers
3666                          * set to the values inherited by the shell
3667                          * from its parent". */
3668                         new_act = S_IGN;
3669                         break;
3670                 case SIGTERM:
3671                         if (iflag)
3672                                 new_act = S_IGN;
3673                         break;
3674 #if JOBS
3675                 case SIGTSTP:
3676                 case SIGTTOU:
3677                         if (mflag)
3678                                 new_act = S_IGN;
3679                         break;
3680 #endif
3681                 }
3682         }
3683         /* if !rootshell, we reset SIGQUIT to DFL,
3684          * whereas we have to restore it to what shell got on entry.
3685          * This is handled by the fact that if signal was IGNored on entry,
3686          * then cur_act is S_HARD_IGN and we never change its sigaction
3687          * (see code below).
3688          */
3689
3690         if (signo == SIGCHLD)
3691                 new_act = S_CATCH;
3692
3693         t = &sigmode[signo - 1];
3694         cur_act = *t;
3695         if (cur_act == 0) {
3696                 /* current setting is not yet known */
3697                 if (sigaction(signo, NULL, &act)) {
3698                         /* pretend it worked; maybe we should give a warning,
3699                          * but other shells don't. We don't alter sigmode,
3700                          * so we retry every time.
3701                          * btw, in Linux it never fails. --vda */
3702                         return;
3703                 }
3704                 if (act.sa_handler == SIG_IGN) {
3705                         cur_act = S_HARD_IGN;
3706                         if (mflag
3707                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3708                         ) {
3709                                 cur_act = S_IGN;   /* don't hard ignore these */
3710                         }
3711                 }
3712                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3713                         /* installing SIG_DFL over SIG_DFL is a no-op */
3714                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3715                         *t = S_DFL;
3716                         return;
3717                 }
3718         }
3719         if (cur_act == S_HARD_IGN || cur_act == new_act)
3720                 return;
3721
3722         *t = new_act;
3723
3724         act.sa_handler = SIG_DFL;
3725         switch (new_act) {
3726         case S_CATCH:
3727                 act.sa_handler = signal_handler;
3728                 break;
3729         case S_IGN:
3730                 act.sa_handler = SIG_IGN;
3731                 break;
3732         }
3733         /* flags and mask matter only if !DFL and !IGN, but we do it
3734          * for all cases for more deterministic behavior:
3735          */
3736         act.sa_flags = 0; //TODO: why not SA_RESTART?
3737         sigfillset(&act.sa_mask);
3738
3739         sigaction_set(signo, &act);
3740 }
3741
3742 /* mode flags for set_curjob */
3743 #define CUR_DELETE 2
3744 #define CUR_RUNNING 1
3745 #define CUR_STOPPED 0
3746
3747 #if JOBS
3748 /* pgrp of shell on invocation */
3749 static int initialpgrp; //references:2
3750 static int ttyfd = -1; //5
3751 #endif
3752 /* array of jobs */
3753 static struct job *jobtab; //5
3754 /* size of array */
3755 static unsigned njobs; //4
3756 /* current job */
3757 static struct job *curjob; //lots
3758 /* number of presumed living untracked jobs */
3759 static int jobless; //4
3760
3761 #if 0
3762 /* Bash has a feature: it restores termios after a successful wait for
3763  * a foreground job which had at least one stopped or sigkilled member.
3764  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3765  * properly restoring tty state. Should we do this too?
3766  * A reproducer: ^Z an interactive python:
3767  *
3768  * # python
3769  * Python 2.7.12 (...)
3770  * >>> ^Z
3771  *      { python leaves tty in -icanon -echo state. We do survive that... }
3772  *  [1]+  Stopped                    python
3773  *      { ...however, next program (python #2) does not survive it well: }
3774  * # python
3775  * Python 2.7.12 (...)
3776  * >>> Traceback (most recent call last):
3777  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3778  *   File "<stdin>", line 1, in <module>
3779  * NameError: name 'qwerty' is not defined
3780  *
3781  * The implementation below is modeled on bash code and seems to work.
3782  * However, I'm not sure we should do this. For one: what if I'd fg
3783  * the stopped python instead? It'll be confused by "restored" tty state.
3784  */
3785 static struct termios shell_tty_info;
3786 static void
3787 get_tty_state(void)
3788 {
3789         if (rootshell && ttyfd >= 0)
3790                 tcgetattr(ttyfd, &shell_tty_info);
3791 }
3792 static void
3793 set_tty_state(void)
3794 {
3795         /* if (rootshell) - caller ensures this */
3796         if (ttyfd >= 0)
3797                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3798 }
3799 static int
3800 job_signal_status(struct job *jp)
3801 {
3802         int status;
3803         unsigned i;
3804         struct procstat *ps = jp->ps;
3805         for (i = 0; i < jp->nprocs; i++) {
3806                 status = ps[i].ps_status;
3807                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3808                         return status;
3809         }
3810         return 0;
3811 }
3812 static void
3813 restore_tty_if_stopped_or_signaled(struct job *jp)
3814 {
3815 //TODO: check what happens if we come from waitforjob() in expbackq()
3816         if (rootshell) {
3817                 int s = job_signal_status(jp);
3818                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3819                         set_tty_state();
3820         }
3821 }
3822 #else
3823 # define get_tty_state() ((void)0)
3824 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3825 #endif
3826
3827 static void
3828 set_curjob(struct job *jp, unsigned mode)
3829 {
3830         struct job *jp1;
3831         struct job **jpp, **curp;
3832
3833         /* first remove from list */
3834         jpp = curp = &curjob;
3835         while (1) {
3836                 jp1 = *jpp;
3837                 if (jp1 == jp)
3838                         break;
3839                 jpp = &jp1->prev_job;
3840         }
3841         *jpp = jp1->prev_job;
3842
3843         /* Then re-insert in correct position */
3844         jpp = curp;
3845         switch (mode) {
3846         default:
3847 #if DEBUG
3848                 abort();
3849 #endif
3850         case CUR_DELETE:
3851                 /* job being deleted */
3852                 break;
3853         case CUR_RUNNING:
3854                 /* newly created job or backgrounded job,
3855                  * put after all stopped jobs.
3856                  */
3857                 while (1) {
3858                         jp1 = *jpp;
3859 #if JOBS
3860                         if (!jp1 || jp1->state != JOBSTOPPED)
3861 #endif
3862                                 break;
3863                         jpp = &jp1->prev_job;
3864                 }
3865                 /* FALLTHROUGH */
3866 #if JOBS
3867         case CUR_STOPPED:
3868 #endif
3869                 /* newly stopped job - becomes curjob */
3870                 jp->prev_job = *jpp;
3871                 *jpp = jp;
3872                 break;
3873         }
3874 }
3875
3876 #if JOBS || DEBUG
3877 static int
3878 jobno(const struct job *jp)
3879 {
3880         return jp - jobtab + 1;
3881 }
3882 #endif
3883
3884 /*
3885  * Convert a job name to a job structure.
3886  */
3887 #if !JOBS
3888 #define getjob(name, getctl) getjob(name)
3889 #endif
3890 static struct job *
3891 getjob(const char *name, int getctl)
3892 {
3893         struct job *jp;
3894         struct job *found;
3895         const char *err_msg = "%s: no such job";
3896         unsigned num;
3897         int c;
3898         const char *p;
3899         char *(*match)(const char *, const char *);
3900
3901         jp = curjob;
3902         p = name;
3903         if (!p)
3904                 goto currentjob;
3905
3906         if (*p != '%')
3907                 goto err;
3908
3909         c = *++p;
3910         if (!c)
3911                 goto currentjob;
3912
3913         if (!p[1]) {
3914                 if (c == '+' || c == '%') {
3915  currentjob:
3916                         err_msg = "No current job";
3917                         goto check;
3918                 }
3919                 if (c == '-') {
3920                         if (jp)
3921                                 jp = jp->prev_job;
3922                         err_msg = "No previous job";
3923  check:
3924                         if (!jp)
3925                                 goto err;
3926                         goto gotit;
3927                 }
3928         }
3929
3930         if (is_number(p)) {
3931                 num = atoi(p);
3932                 if (num > 0 && num <= njobs) {
3933                         jp = jobtab + num - 1;
3934                         if (jp->used)
3935                                 goto gotit;
3936                         goto err;
3937                 }
3938         }
3939
3940         match = prefix;
3941         if (*p == '?') {
3942                 match = strstr;
3943                 p++;
3944         }
3945
3946         found = NULL;
3947         while (jp) {
3948                 if (match(jp->ps[0].ps_cmd, p)) {
3949                         if (found)
3950                                 goto err;
3951                         found = jp;
3952                         err_msg = "%s: ambiguous";
3953                 }
3954                 jp = jp->prev_job;
3955         }
3956         if (!found)
3957                 goto err;
3958         jp = found;
3959
3960  gotit:
3961 #if JOBS
3962         err_msg = "job %s not created under job control";
3963         if (getctl && jp->jobctl == 0)
3964                 goto err;
3965 #endif
3966         return jp;
3967  err:
3968         ash_msg_and_raise_error(err_msg, name);
3969 }
3970
3971 /*
3972  * Mark a job structure as unused.
3973  */
3974 static void
3975 freejob(struct job *jp)
3976 {
3977         struct procstat *ps;
3978         int i;
3979
3980         INT_OFF;
3981         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3982                 if (ps->ps_cmd != nullstr)
3983                         free(ps->ps_cmd);
3984         }
3985         if (jp->ps != &jp->ps0)
3986                 free(jp->ps);
3987         jp->used = 0;
3988         set_curjob(jp, CUR_DELETE);
3989         INT_ON;
3990 }
3991
3992 #if JOBS
3993 static void
3994 xtcsetpgrp(int fd, pid_t pgrp)
3995 {
3996         if (tcsetpgrp(fd, pgrp))
3997                 ash_msg_and_raise_perror("can't set tty process group");
3998 }
3999
4000 /*
4001  * Turn job control on and off.
4002  *
4003  * Note:  This code assumes that the third arg to ioctl is a character
4004  * pointer, which is true on Berkeley systems but not System V.  Since
4005  * System V doesn't have job control yet, this isn't a problem now.
4006  *
4007  * Called with interrupts off.
4008  */
4009 static void
4010 setjobctl(int on)
4011 {
4012         int fd;
4013         int pgrp;
4014
4015         if (on == doing_jobctl || rootshell == 0)
4016                 return;
4017         if (on) {
4018                 int ofd;
4019                 ofd = fd = open(_PATH_TTY, O_RDWR);
4020                 if (fd < 0) {
4021         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4022          * That sometimes helps to acquire controlling tty.
4023          * Obviously, a workaround for bugs when someone
4024          * failed to provide a controlling tty to bash! :) */
4025                         fd = 2;
4026                         while (!isatty(fd))
4027                                 if (--fd < 0)
4028                                         goto out;
4029                 }
4030                 /* fd is a tty at this point */
4031                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4032                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4033                         close(ofd);
4034                 if (fd < 0)
4035                         goto out; /* F_DUPFD failed */
4036                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4037                         close_on_exec_on(fd);
4038                 while (1) { /* while we are in the background */
4039                         pgrp = tcgetpgrp(fd);
4040                         if (pgrp < 0) {
4041  out:
4042                                 ash_msg("can't access tty; job control turned off");
4043                                 mflag = on = 0;
4044                                 goto close;
4045                         }
4046                         if (pgrp == getpgrp())
4047                                 break;
4048                         killpg(0, SIGTTIN);
4049                 }
4050                 initialpgrp = pgrp;
4051
4052                 setsignal(SIGTSTP);
4053                 setsignal(SIGTTOU);
4054                 setsignal(SIGTTIN);
4055                 pgrp = rootpid;
4056                 setpgid(0, pgrp);
4057                 xtcsetpgrp(fd, pgrp);
4058         } else {
4059                 /* turning job control off */
4060                 fd = ttyfd;
4061                 pgrp = initialpgrp;
4062                 /* was xtcsetpgrp, but this can make exiting ash
4063                  * loop forever if pty is already deleted */
4064                 tcsetpgrp(fd, pgrp);
4065                 setpgid(0, pgrp);
4066                 setsignal(SIGTSTP);
4067                 setsignal(SIGTTOU);
4068                 setsignal(SIGTTIN);
4069  close:
4070                 if (fd >= 0)
4071                         close(fd);
4072                 fd = -1;
4073         }
4074         ttyfd = fd;
4075         doing_jobctl = on;
4076 }
4077
4078 static int FAST_FUNC
4079 killcmd(int argc, char **argv)
4080 {
4081         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4082                 int i = 1;
4083                 do {
4084                         if (argv[i][0] == '%') {
4085                                 /*
4086                                  * "kill %N" - job kill
4087                                  * Converting to pgrp / pid kill
4088                                  */
4089                                 struct job *jp;
4090                                 char *dst;
4091                                 int j, n;
4092
4093                                 jp = getjob(argv[i], 0);
4094                                 /*
4095                                  * In jobs started under job control, we signal
4096                                  * entire process group by kill -PGRP_ID.
4097                                  * This happens, f.e., in interactive shell.
4098                                  *
4099                                  * Otherwise, we signal each child via
4100                                  * kill PID1 PID2 PID3.
4101                                  * Testcases:
4102                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4103                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4104                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4105                                  */
4106                                 n = jp->nprocs; /* can't be 0 (I hope) */
4107                                 if (jp->jobctl)
4108                                         n = 1;
4109                                 dst = alloca(n * sizeof(int)*4);
4110                                 argv[i] = dst;
4111                                 for (j = 0; j < n; j++) {
4112                                         struct procstat *ps = &jp->ps[j];
4113                                         /* Skip non-running and not-stopped members
4114                                          * (i.e. dead members) of the job
4115                                          */
4116                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4117                                                 continue;
4118                                         /*
4119                                          * kill_main has matching code to expect
4120                                          * leading space. Needed to not confuse
4121                                          * negative pids with "kill -SIGNAL_NO" syntax
4122                                          */
4123                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4124                                 }
4125                                 *dst = '\0';
4126                         }
4127                 } while (argv[++i]);
4128         }
4129         return kill_main(argc, argv);
4130 }
4131
4132 static void
4133 showpipe(struct job *jp /*, FILE *out*/)
4134 {
4135         struct procstat *ps;
4136         struct procstat *psend;
4137
4138         psend = jp->ps + jp->nprocs;
4139         for (ps = jp->ps + 1; ps < psend; ps++)
4140                 printf(" | %s", ps->ps_cmd);
4141         newline_and_flush(stdout);
4142         flush_stdout_stderr();
4143 }
4144
4145
4146 static int
4147 restartjob(struct job *jp, int mode)
4148 {
4149         struct procstat *ps;
4150         int i;
4151         int status;
4152         pid_t pgid;
4153
4154         INT_OFF;
4155         if (jp->state == JOBDONE)
4156                 goto out;
4157         jp->state = JOBRUNNING;
4158         pgid = jp->ps[0].ps_pid;
4159         if (mode == FORK_FG) {
4160                 get_tty_state();
4161                 xtcsetpgrp(ttyfd, pgid);
4162         }
4163         killpg(pgid, SIGCONT);
4164         ps = jp->ps;
4165         i = jp->nprocs;
4166         do {
4167                 if (WIFSTOPPED(ps->ps_status)) {
4168                         ps->ps_status = -1;
4169                 }
4170                 ps++;
4171         } while (--i);
4172  out:
4173         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4174         INT_ON;
4175         return status;
4176 }
4177
4178 static int FAST_FUNC
4179 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4180 {
4181         struct job *jp;
4182         int mode;
4183         int retval;
4184
4185         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4186         nextopt(nullstr);
4187         argv = argptr;
4188         do {
4189                 jp = getjob(*argv, 1);
4190                 if (mode == FORK_BG) {
4191                         set_curjob(jp, CUR_RUNNING);
4192                         printf("[%d] ", jobno(jp));
4193                 }
4194                 out1str(jp->ps[0].ps_cmd);
4195                 showpipe(jp /*, stdout*/);
4196                 retval = restartjob(jp, mode);
4197         } while (*argv && *++argv);
4198         return retval;
4199 }
4200 #endif
4201
4202 static int
4203 sprint_status48(char *s, int status, int sigonly)
4204 {
4205         int col;
4206         int st;
4207
4208         col = 0;
4209         if (!WIFEXITED(status)) {
4210 #if JOBS
4211                 if (WIFSTOPPED(status))
4212                         st = WSTOPSIG(status);
4213                 else
4214 #endif
4215                         st = WTERMSIG(status);
4216                 if (sigonly) {
4217                         if (st == SIGINT || st == SIGPIPE)
4218                                 goto out;
4219 #if JOBS
4220                         if (WIFSTOPPED(status))
4221                                 goto out;
4222 #endif
4223                 }
4224                 st &= 0x7f;
4225 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4226                 col = fmtstr(s, 32, strsignal(st));
4227                 if (WCOREDUMP(status)) {
4228                         strcpy(s + col, " (core dumped)");
4229                         col += sizeof(" (core dumped)")-1;
4230                 }
4231         } else if (!sigonly) {
4232                 st = WEXITSTATUS(status);
4233                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4234         }
4235  out:
4236         return col;
4237 }
4238
4239 static int
4240 wait_block_or_sig(int *status)
4241 {
4242         int pid;
4243
4244         do {
4245                 sigset_t mask;
4246
4247                 /* Poll all children for changes in their state */
4248                 got_sigchld = 0;
4249                 /* if job control is active, accept stopped processes too */
4250                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4251                 if (pid != 0)
4252                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4253
4254                 /* Children exist, but none are ready. Sleep until interesting signal */
4255 #if 1
4256                 sigfillset(&mask);
4257                 sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
4258                 while (!got_sigchld && !pending_sig)
4259                         sigsuspend(&mask);
4260                 sigprocmask(SIG_SETMASK, &mask, NULL);
4261 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4262                 while (!got_sigchld && !pending_sig)
4263                         pause();
4264 #endif
4265
4266                 /* If it was SIGCHLD, poll children again */
4267         } while (got_sigchld);
4268
4269         return pid;
4270 }
4271
4272 #define DOWAIT_NONBLOCK 0
4273 #define DOWAIT_BLOCK    1
4274 #define DOWAIT_BLOCK_OR_SIG 2
4275 #if BASH_WAIT_N
4276 # define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4277 #endif
4278
4279 static int
4280 dowait(int block, struct job *job)
4281 {
4282         int pid;
4283         int status;
4284         struct job *jp;
4285         struct job *thisjob;
4286 #if BASH_WAIT_N
4287         bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4288         block = (block & ~DOWAIT_JOBSTATUS);
4289 #endif
4290
4291         TRACE(("dowait(0x%x) called\n", block));
4292
4293         /* It's wrong to call waitpid() outside of INT_OFF region:
4294          * signal can arrive just after syscall return and handler can
4295          * longjmp away, losing stop/exit notification processing.
4296          * Thus, for "jobs" builtin, and for waiting for a fg job,
4297          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4298          *
4299          * However, for "wait" builtin it is wrong to simply call waitpid()
4300          * in INT_OFF region: "wait" needs to wait for any running job
4301          * to change state, but should exit on any trap too.
4302          * In INT_OFF region, a signal just before syscall entry can set
4303          * pending_sig variables, but we can't check them, and we would
4304          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4305          *
4306          * Because of this, we run inside INT_OFF, but use a special routine
4307          * which combines waitpid() and sigsuspend().
4308          * This is the reason why we need to have a handler for SIGCHLD:
4309          * SIG_DFL handler does not wake sigsuspend().
4310          */
4311         INT_OFF;
4312         if (block == DOWAIT_BLOCK_OR_SIG) {
4313                 pid = wait_block_or_sig(&status);
4314         } else {
4315                 int wait_flags = 0;
4316                 if (block == DOWAIT_NONBLOCK)
4317                         wait_flags = WNOHANG;
4318                 /* if job control is active, accept stopped processes too */
4319                 if (doing_jobctl)
4320                         wait_flags |= WUNTRACED;
4321                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4322                 pid = waitpid(-1, &status, wait_flags);
4323         }
4324         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4325                                 pid, status, errno, strerror(errno)));
4326         thisjob = NULL;
4327         if (pid <= 0)
4328                 goto out;
4329
4330         for (jp = curjob; jp; jp = jp->prev_job) {
4331                 int jobstate;
4332                 struct procstat *ps;
4333                 struct procstat *psend;
4334                 if (jp->state == JOBDONE)
4335                         continue;
4336                 jobstate = JOBDONE;
4337                 ps = jp->ps;
4338                 psend = ps + jp->nprocs;
4339                 do {
4340                         if (ps->ps_pid == pid) {
4341                                 TRACE(("Job %d: changing status of proc %d "
4342                                         "from 0x%x to 0x%x\n",
4343                                         jobno(jp), pid, ps->ps_status, status));
4344                                 ps->ps_status = status;
4345                                 thisjob = jp;
4346                         }
4347                         if (ps->ps_status == -1)
4348                                 jobstate = JOBRUNNING;
4349 #if JOBS
4350                         if (jobstate == JOBRUNNING)
4351                                 continue;
4352                         if (WIFSTOPPED(ps->ps_status)) {
4353                                 jp->stopstatus = ps->ps_status;
4354                                 jobstate = JOBSTOPPED;
4355                         }
4356 #endif
4357                 } while (++ps < psend);
4358                 if (!thisjob)
4359                         continue;
4360
4361                 /* Found the job where one of its processes changed its state.
4362                  * Is there at least one live and running process in this job? */
4363                 if (jobstate != JOBRUNNING) {
4364                         /* No. All live processes in the job are stopped
4365                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4366                          */
4367                         thisjob->changed = 1;
4368                         if (thisjob->state != jobstate) {
4369                                 TRACE(("Job %d: changing state from %d to %d\n",
4370                                         jobno(thisjob), thisjob->state, jobstate));
4371                                 thisjob->state = jobstate;
4372 #if JOBS
4373                                 if (jobstate == JOBSTOPPED)
4374                                         set_curjob(thisjob, CUR_STOPPED);
4375 #endif
4376                         }
4377                 }
4378                 goto out;
4379         }
4380         /* The process wasn't found in job list */
4381 #if JOBS
4382         if (!WIFSTOPPED(status))
4383                 jobless--;
4384 #endif
4385  out:
4386         INT_ON;
4387
4388 #if BASH_WAIT_N
4389         if (want_jobexitstatus) {
4390                 pid = -1;
4391                 if (thisjob && thisjob->state == JOBDONE)
4392                         pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4393         }
4394 #endif
4395         if (thisjob && thisjob == job) {
4396                 char s[48 + 1];
4397                 int len;
4398
4399                 len = sprint_status48(s, status, 1);
4400                 if (len) {
4401                         s[len] = '\n';
4402                         s[len + 1] = '\0';
4403                         out2str(s);
4404                 }
4405         }
4406         return pid;
4407 }
4408
4409 #if JOBS
4410 static void
4411 showjob(struct job *jp, int mode)
4412 {
4413         struct procstat *ps;
4414         struct procstat *psend;
4415         int col;
4416         int indent_col;
4417         char s[16 + 16 + 48];
4418         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4419
4420         ps = jp->ps;
4421
4422         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4423                 /* just output process (group) id of pipeline */
4424                 fprintf(out, "%d\n", ps->ps_pid);
4425                 return;
4426         }
4427
4428         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4429         indent_col = col;
4430
4431         if (jp == curjob)
4432                 s[col - 3] = '+';
4433         else if (curjob && jp == curjob->prev_job)
4434                 s[col - 3] = '-';
4435
4436         if (mode & SHOW_PIDS)
4437                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4438
4439         psend = ps + jp->nprocs;
4440
4441         if (jp->state == JOBRUNNING) {
4442                 strcpy(s + col, "Running");
4443                 col += sizeof("Running") - 1;
4444         } else {
4445                 int status = psend[-1].ps_status;
4446                 if (jp->state == JOBSTOPPED)
4447                         status = jp->stopstatus;
4448                 col += sprint_status48(s + col, status, 0);
4449         }
4450         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4451
4452         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4453          * or prints several "PID             | <cmdN>" lines,
4454          * depending on SHOW_PIDS bit.
4455          * We do not print status of individual processes
4456          * between PID and <cmdN>. bash does it, but not very well:
4457          * first line shows overall job status, not process status,
4458          * making it impossible to know 1st process status.
4459          */
4460         goto start;
4461         do {
4462                 /* for each process */
4463                 s[0] = '\0';
4464                 col = 33;
4465                 if (mode & SHOW_PIDS)
4466                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4467  start:
4468                 fprintf(out, "%s%*c%s%s",
4469                                 s,
4470                                 33 - col >= 0 ? 33 - col : 0, ' ',
4471                                 ps == jp->ps ? "" : "| ",
4472                                 ps->ps_cmd
4473                 );
4474         } while (++ps != psend);
4475         newline_and_flush(out);
4476
4477         jp->changed = 0;
4478
4479         if (jp->state == JOBDONE) {
4480                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4481                 freejob(jp);
4482         }
4483 }
4484
4485 /*
4486  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4487  * statuses have changed since the last call to showjobs.
4488  */
4489 static void
4490 showjobs(int mode)
4491 {
4492         struct job *jp;
4493
4494         TRACE(("showjobs(0x%x) called\n", mode));
4495
4496         /* Handle all finished jobs */
4497         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4498                 continue;
4499
4500         for (jp = curjob; jp; jp = jp->prev_job) {
4501                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4502                         showjob(jp, mode);
4503                 }
4504         }
4505 }
4506
4507 static int FAST_FUNC
4508 jobscmd(int argc UNUSED_PARAM, char **argv)
4509 {
4510         int mode, m;
4511
4512         mode = 0;
4513         while ((m = nextopt("lp")) != '\0') {
4514                 if (m == 'l')
4515                         mode |= SHOW_PIDS;
4516                 else
4517                         mode |= SHOW_ONLY_PGID;
4518         }
4519
4520         argv = argptr;
4521         if (*argv) {
4522                 do
4523                         showjob(getjob(*argv, 0), mode);
4524                 while (*++argv);
4525         } else {
4526                 showjobs(mode);
4527         }
4528
4529         return 0;
4530 }
4531 #endif /* JOBS */
4532
4533 /* Called only on finished or stopped jobs (no members are running) */
4534 static int
4535 getstatus(struct job *job)
4536 {
4537         int status;
4538         int retval;
4539         struct procstat *ps;
4540
4541         /* Fetch last member's status */
4542         ps = job->ps + job->nprocs - 1;
4543         status = ps->ps_status;
4544         if (pipefail) {
4545                 /* "set -o pipefail" mode: use last _nonzero_ status */
4546                 while (status == 0 && --ps >= job->ps)
4547                         status = ps->ps_status;
4548         }
4549
4550         retval = WEXITSTATUS(status);
4551         if (!WIFEXITED(status)) {
4552 #if JOBS
4553                 retval = WSTOPSIG(status);
4554                 if (!WIFSTOPPED(status))
4555 #endif
4556                 {
4557                         /* XXX: limits number of signals */
4558                         retval = WTERMSIG(status);
4559 #if JOBS
4560                         if (retval == SIGINT)
4561                                 job->sigint = 1;
4562 #endif
4563                 }
4564                 retval += 128;
4565         }
4566         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4567                 jobno(job), job->nprocs, status, retval));
4568         return retval;
4569 }
4570
4571 static int FAST_FUNC
4572 waitcmd(int argc UNUSED_PARAM, char **argv)
4573 {
4574         struct job *job;
4575         int retval;
4576         struct job *jp;
4577 #if BASH_WAIT_N
4578         int status;
4579         char one = nextopt("n");
4580 #else
4581         nextopt(nullstr);
4582 #endif
4583         retval = 0;
4584
4585         argv = argptr;
4586         if (!argv[0]) {
4587                 /* wait for all jobs / one job if -n */
4588                 for (;;) {
4589                         jp = curjob;
4590 #if BASH_WAIT_N
4591                         if (one && !jp)
4592                                 /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4593                                 retval = 127;
4594 #endif
4595                         while (1) {
4596                                 if (!jp) /* no running procs */
4597                                         goto ret;
4598                                 if (jp->state == JOBRUNNING)
4599                                         break;
4600                                 jp->waited = 1;
4601                                 jp = jp->prev_job;
4602                         }
4603         /* man bash:
4604          * "When bash is waiting for an asynchronous command via
4605          * the wait builtin, the reception of a signal for which a trap
4606          * has been set will cause the wait builtin to return immediately
4607          * with an exit status greater than 128, immediately after which
4608          * the trap is executed."
4609          */
4610 #if BASH_WAIT_N
4611                         status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4612 #else
4613                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4614 #endif
4615         /* if child sends us a signal *and immediately exits*,
4616          * dowait() returns pid > 0. Check this case,
4617          * not "if (dowait() < 0)"!
4618          */
4619                         if (pending_sig)
4620                                 goto sigout;
4621 #if BASH_WAIT_N
4622                         if (one) {
4623                                 /* wait -n waits for one _job_, not one _process_.
4624                                  *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4625                                  * should wait for 2 seconds. Not 1 or 3.
4626                                  */
4627                                 if (status != -1 && !WIFSTOPPED(status)) {
4628                                         retval = WEXITSTATUS(status);
4629                                         if (WIFSIGNALED(status))
4630                                                 retval = WTERMSIG(status) + 128;
4631                                         goto ret;
4632                                 }
4633                         }
4634 #endif
4635                 }
4636         }
4637
4638         retval = 127;
4639         do {
4640                 if (**argv != '%') {
4641                         pid_t pid = number(*argv);
4642                         job = curjob;
4643                         while (1) {
4644                                 if (!job)
4645                                         goto repeat;
4646                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4647                                         break;
4648                                 job = job->prev_job;
4649                         }
4650                 } else {
4651                         job = getjob(*argv, 0);
4652                 }
4653                 /* loop until process terminated or stopped */
4654                 while (job->state == JOBRUNNING) {
4655                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4656                         if (pending_sig)
4657                                 goto sigout;
4658                 }
4659                 job->waited = 1;
4660                 retval = getstatus(job);
4661  repeat: ;
4662         } while (*++argv);
4663
4664  ret:
4665         return retval;
4666  sigout:
4667         retval = 128 + pending_sig;
4668         return retval;
4669 }
4670
4671 static struct job *
4672 growjobtab(void)
4673 {
4674         size_t len;
4675         ptrdiff_t offset;
4676         struct job *jp, *jq;
4677
4678         len = njobs * sizeof(*jp);
4679         jq = jobtab;
4680         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4681
4682         offset = (char *)jp - (char *)jq;
4683         if (offset) {
4684                 /* Relocate pointers */
4685                 size_t l = len;
4686
4687                 jq = (struct job *)((char *)jq + l);
4688                 while (l) {
4689                         l -= sizeof(*jp);
4690                         jq--;
4691 #define joff(p) ((struct job *)((char *)(p) + l))
4692 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4693                         if (joff(jp)->ps == &jq->ps0)
4694                                 jmove(joff(jp)->ps);
4695                         if (joff(jp)->prev_job)
4696                                 jmove(joff(jp)->prev_job);
4697                 }
4698                 if (curjob)
4699                         jmove(curjob);
4700 #undef joff
4701 #undef jmove
4702         }
4703
4704         njobs += 4;
4705         jobtab = jp;
4706         jp = (struct job *)((char *)jp + len);
4707         jq = jp + 3;
4708         do {
4709                 jq->used = 0;
4710         } while (--jq >= jp);
4711         return jp;
4712 }
4713
4714 /*
4715  * Return a new job structure.
4716  * Called with interrupts off.
4717  */
4718 static struct job *
4719 makejob(/*union node *node,*/ int nprocs)
4720 {
4721         int i;
4722         struct job *jp;
4723
4724         for (i = njobs, jp = jobtab; ; jp++) {
4725                 if (--i < 0) {
4726                         jp = growjobtab();
4727                         break;
4728                 }
4729                 if (jp->used == 0)
4730                         break;
4731                 if (jp->state != JOBDONE || !jp->waited)
4732                         continue;
4733 #if JOBS
4734                 if (doing_jobctl)
4735                         continue;
4736 #endif
4737                 freejob(jp);
4738                 break;
4739         }
4740         memset(jp, 0, sizeof(*jp));
4741 #if JOBS
4742         /* jp->jobctl is a bitfield.
4743          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4744         if (doing_jobctl)
4745                 jp->jobctl = 1;
4746 #endif
4747         jp->prev_job = curjob;
4748         curjob = jp;
4749         jp->used = 1;
4750         jp->ps = &jp->ps0;
4751         if (nprocs > 1) {
4752                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4753         }
4754         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4755                                 jobno(jp)));
4756         return jp;
4757 }
4758
4759 #if JOBS
4760 /*
4761  * Return a string identifying a command (to be printed by the
4762  * jobs command).
4763  */
4764 static char *cmdnextc;
4765
4766 static void
4767 cmdputs(const char *s)
4768 {
4769         static const char vstype[VSTYPE + 1][3] = {
4770                 "", "}", "-", "+", "?", "=",
4771                 "%", "%%", "#", "##"
4772                 IF_BASH_SUBSTR(, ":")
4773                 IF_BASH_PATTERN_SUBST(, "/", "//")
4774         };
4775
4776         const char *p, *str;
4777         char cc[2];
4778         char *nextc;
4779         unsigned char c;
4780         unsigned char subtype = 0;
4781         int quoted = 0;
4782
4783         cc[1] = '\0';
4784         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4785         p = s;
4786         while ((c = *p++) != '\0') {
4787                 str = NULL;
4788                 switch (c) {
4789                 case CTLESC:
4790                         c = *p++;
4791                         break;
4792                 case CTLVAR:
4793                         subtype = *p++;
4794                         if ((subtype & VSTYPE) == VSLENGTH)
4795                                 str = "${#";
4796                         else
4797                                 str = "${";
4798                         goto dostr;
4799                 case CTLENDVAR:
4800                         str = "\"}" + !(quoted & 1);
4801                         quoted >>= 1;
4802                         subtype = 0;
4803                         goto dostr;
4804                 case CTLBACKQ:
4805                         str = "$(...)";
4806                         goto dostr;
4807 #if ENABLE_FEATURE_SH_MATH
4808                 case CTLARI:
4809                         str = "$((";
4810                         goto dostr;
4811                 case CTLENDARI:
4812                         str = "))";
4813                         goto dostr;
4814 #endif
4815                 case CTLQUOTEMARK:
4816                         quoted ^= 1;
4817                         c = '"';
4818                         break;
4819                 case '=':
4820                         if (subtype == 0)
4821                                 break;
4822                         if ((subtype & VSTYPE) != VSNORMAL)
4823                                 quoted <<= 1;
4824                         str = vstype[subtype & VSTYPE];
4825                         if (subtype & VSNUL)
4826                                 c = ':';
4827                         else
4828                                 goto checkstr;
4829                         break;
4830                 case '\'':
4831                 case '\\':
4832                 case '"':
4833                 case '$':
4834                         /* These can only happen inside quotes */
4835                         cc[0] = c;
4836                         str = cc;
4837 //FIXME:
4838 // $ true $$ &
4839 // $ <cr>
4840 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4841                         c = '\\';
4842                         break;
4843                 default:
4844                         break;
4845                 }
4846                 USTPUTC(c, nextc);
4847  checkstr:
4848                 if (!str)
4849                         continue;
4850  dostr:
4851                 while ((c = *str++) != '\0') {
4852                         USTPUTC(c, nextc);
4853                 }
4854         } /* while *p++ not NUL */
4855
4856         if (quoted & 1) {
4857                 USTPUTC('"', nextc);
4858         }
4859         *nextc = 0;
4860         cmdnextc = nextc;
4861 }
4862
4863 /* cmdtxt() and cmdlist() call each other */
4864 static void cmdtxt(union node *n);
4865
4866 static void
4867 cmdlist(union node *np, int sep)
4868 {
4869         for (; np; np = np->narg.next) {
4870                 if (!sep)
4871                         cmdputs(" ");
4872                 cmdtxt(np);
4873                 if (sep && np->narg.next)
4874                         cmdputs(" ");
4875         }
4876 }
4877
4878 static void
4879 cmdtxt(union node *n)
4880 {
4881         union node *np;
4882         struct nodelist *lp;
4883         const char *p;
4884
4885         if (!n)
4886                 return;
4887         switch (n->type) {
4888         default:
4889 #if DEBUG
4890                 abort();
4891 #endif
4892         case NPIPE:
4893                 lp = n->npipe.cmdlist;
4894                 for (;;) {
4895                         cmdtxt(lp->n);
4896                         lp = lp->next;
4897                         if (!lp)
4898                                 break;
4899                         cmdputs(" | ");
4900                 }
4901                 break;
4902         case NSEMI:
4903                 p = "; ";
4904                 goto binop;
4905         case NAND:
4906                 p = " && ";
4907                 goto binop;
4908         case NOR:
4909                 p = " || ";
4910  binop:
4911                 cmdtxt(n->nbinary.ch1);
4912                 cmdputs(p);
4913                 n = n->nbinary.ch2;
4914                 goto donode;
4915         case NREDIR:
4916         case NBACKGND:
4917                 n = n->nredir.n;
4918                 goto donode;
4919         case NNOT:
4920                 cmdputs("!");
4921                 n = n->nnot.com;
4922  donode:
4923                 cmdtxt(n);
4924                 break;
4925         case NIF:
4926                 cmdputs("if ");
4927                 cmdtxt(n->nif.test);
4928                 cmdputs("; then ");
4929                 if (n->nif.elsepart) {
4930                         cmdtxt(n->nif.ifpart);
4931                         cmdputs("; else ");
4932                         n = n->nif.elsepart;
4933                 } else {
4934                         n = n->nif.ifpart;
4935                 }
4936                 p = "; fi";
4937                 goto dotail;
4938         case NSUBSHELL:
4939                 cmdputs("(");
4940                 n = n->nredir.n;
4941                 p = ")";
4942                 goto dotail;
4943         case NWHILE:
4944                 p = "while ";
4945                 goto until;
4946         case NUNTIL:
4947                 p = "until ";
4948  until:
4949                 cmdputs(p);
4950                 cmdtxt(n->nbinary.ch1);
4951                 n = n->nbinary.ch2;
4952                 p = "; done";
4953  dodo:
4954                 cmdputs("; do ");
4955  dotail:
4956                 cmdtxt(n);
4957                 goto dotail2;
4958         case NFOR:
4959                 cmdputs("for ");
4960                 cmdputs(n->nfor.var);
4961                 cmdputs(" in ");
4962                 cmdlist(n->nfor.args, 1);
4963                 n = n->nfor.body;
4964                 p = "; done";
4965                 goto dodo;
4966         case NDEFUN:
4967                 cmdputs(n->ndefun.text);
4968                 p = "() { ... }";
4969                 goto dotail2;
4970         case NCMD:
4971                 cmdlist(n->ncmd.args, 1);
4972                 cmdlist(n->ncmd.redirect, 0);
4973                 break;
4974         case NARG:
4975                 p = n->narg.text;
4976  dotail2:
4977                 cmdputs(p);
4978                 break;
4979         case NHERE:
4980         case NXHERE:
4981                 p = "<<...";
4982                 goto dotail2;
4983         case NCASE:
4984                 cmdputs("case ");
4985                 cmdputs(n->ncase.expr->narg.text);
4986                 cmdputs(" in ");
4987                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4988                         cmdtxt(np->nclist.pattern);
4989                         cmdputs(") ");
4990                         cmdtxt(np->nclist.body);
4991                         cmdputs(";; ");
4992                 }
4993                 p = "esac";
4994                 goto dotail2;
4995         case NTO:
4996                 p = ">";
4997                 goto redir;
4998         case NCLOBBER:
4999                 p = ">|";
5000                 goto redir;
5001         case NAPPEND:
5002                 p = ">>";
5003                 goto redir;
5004 #if BASH_REDIR_OUTPUT
5005         case NTO2:
5006 #endif
5007         case NTOFD:
5008                 p = ">&";
5009                 goto redir;
5010         case NFROM:
5011                 p = "<";
5012                 goto redir;
5013         case NFROMFD:
5014                 p = "<&";
5015                 goto redir;
5016         case NFROMTO:
5017                 p = "<>";
5018  redir:
5019                 cmdputs(utoa(n->nfile.fd));
5020                 cmdputs(p);
5021                 if (n->type == NTOFD || n->type == NFROMFD) {
5022                         if (n->ndup.dupfd >= 0)
5023                                 cmdputs(utoa(n->ndup.dupfd));
5024                         else
5025                                 cmdputs("-");
5026                         break;
5027                 }
5028                 n = n->nfile.fname;
5029                 goto donode;
5030         }
5031 }
5032
5033 static char *
5034 commandtext(union node *n)
5035 {
5036         char *name;
5037
5038         STARTSTACKSTR(cmdnextc);
5039         cmdtxt(n);
5040         name = stackblock();
5041         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5042         return ckstrdup(name);
5043 }
5044 #endif /* JOBS */
5045
5046 /*
5047  * Fork off a subshell.  If we are doing job control, give the subshell its
5048  * own process group.  Jp is a job structure that the job is to be added to.
5049  * N is the command that will be evaluated by the child.  Both jp and n may
5050  * be NULL.  The mode parameter can be one of the following:
5051  *      FORK_FG - Fork off a foreground process.
5052  *      FORK_BG - Fork off a background process.
5053  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5054  *                   process group even if job control is on.
5055  *
5056  * When job control is turned off, background processes have their standard
5057  * input redirected to /dev/null (except for the second and later processes
5058  * in a pipeline).
5059  *
5060  * Called with interrupts off.
5061  */
5062 /*
5063  * Clear traps on a fork.
5064  */
5065 static void
5066 clear_traps(void)
5067 {
5068         char **tp;
5069
5070         INT_OFF;
5071         for (tp = trap; tp < &trap[NSIG]; tp++) {
5072                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5073                         if (trap_ptr == trap)
5074                                 free(*tp);
5075                         /* else: it "belongs" to trap_ptr vector, don't free */
5076                         *tp = NULL;
5077                         if ((tp - trap) != 0)
5078                                 setsignal(tp - trap);
5079                 }
5080         }
5081         may_have_traps = 0;
5082         INT_ON;
5083 }
5084
5085 /* Lives far away from here, needed for forkchild */
5086 static void closescript(void);
5087
5088 /* Called after fork(), in child */
5089 /* jp and n are NULL when called by openhere() for heredoc support */
5090 static NOINLINE void
5091 forkchild(struct job *jp, union node *n, int mode)
5092 {
5093         int oldlvl;
5094
5095         TRACE(("Child shell %d\n", getpid()));
5096         oldlvl = shlvl;
5097         shlvl++;
5098
5099         /* man bash: "Non-builtin commands run by bash have signal handlers
5100          * set to the values inherited by the shell from its parent".
5101          * Do we do it correctly? */
5102
5103         closescript();
5104
5105         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5106          && n && n->type == NCMD        /* is it single cmd? */
5107         /* && n->ncmd.args->type == NARG - always true? */
5108          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5109          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5110         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5111         ) {
5112                 TRACE(("Trap hack\n"));
5113                 /* Awful hack for `trap` or $(trap).
5114                  *
5115                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5116                  * contains an example where "trap" is executed in a subshell:
5117                  *
5118                  * save_traps=$(trap)
5119                  * ...
5120                  * eval "$save_traps"
5121                  *
5122                  * Standard does not say that "trap" in subshell shall print
5123                  * parent shell's traps. It only says that its output
5124                  * must have suitable form, but then, in the above example
5125                  * (which is not supposed to be normative), it implies that.
5126                  *
5127                  * bash (and probably other shell) does implement it
5128                  * (traps are reset to defaults, but "trap" still shows them),
5129                  * but as a result, "trap" logic is hopelessly messed up:
5130                  *
5131                  * # trap
5132                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5133                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5134                  * # true | trap   <--- trap is in subshell - no output (ditto)
5135                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5136                  * trap -- 'echo Ho' SIGWINCH
5137                  * # echo `(trap)`         <--- in subshell in subshell - output
5138                  * trap -- 'echo Ho' SIGWINCH
5139                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5140                  * trap -- 'echo Ho' SIGWINCH
5141                  *
5142                  * The rules when to forget and when to not forget traps
5143                  * get really complex and nonsensical.
5144                  *
5145                  * Our solution: ONLY bare $(trap) or `trap` is special.
5146                  */
5147                 /* Save trap handler strings for trap builtin to print */
5148                 trap_ptr = xmemdup(trap, sizeof(trap));
5149                 /* Fall through into clearing traps */
5150         }
5151         clear_traps();
5152 #if JOBS
5153         /* do job control only in root shell */
5154         doing_jobctl = 0;
5155         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5156                 pid_t pgrp;
5157
5158                 if (jp->nprocs == 0)
5159                         pgrp = getpid();
5160                 else
5161                         pgrp = jp->ps[0].ps_pid;
5162                 /* this can fail because we are doing it in the parent also */
5163                 setpgid(0, pgrp);
5164                 if (mode == FORK_FG)
5165                         xtcsetpgrp(ttyfd, pgrp);
5166                 setsignal(SIGTSTP);
5167                 setsignal(SIGTTOU);
5168         } else
5169 #endif
5170         if (mode == FORK_BG) {
5171                 /* man bash: "When job control is not in effect,
5172                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5173                 ignoresig(SIGINT);
5174                 ignoresig(SIGQUIT);
5175                 if (jp->nprocs == 0) {
5176                         close(0);
5177                         if (open(bb_dev_null, O_RDONLY) != 0)
5178                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5179                 }
5180         }
5181         if (oldlvl == 0) {
5182                 if (iflag) { /* why if iflag only? */
5183                         setsignal(SIGINT);
5184                         setsignal(SIGTERM);
5185                 }
5186                 /* man bash:
5187                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5188                  * commands run by bash have signal handlers
5189                  * set to the values inherited by the shell
5190                  * from its parent".
5191                  * Take care of the second rule: */
5192                 setsignal(SIGQUIT);
5193         }
5194 #if JOBS
5195         if (n && n->type == NCMD
5196          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5197         ) {
5198                 TRACE(("Job hack\n"));
5199                 /* "jobs": we do not want to clear job list for it,
5200                  * instead we remove only _its_ own_ job from job list.
5201                  * This makes "jobs .... | cat" more useful.
5202                  */
5203                 freejob(curjob);
5204                 return;
5205         }
5206 #endif
5207         for (jp = curjob; jp; jp = jp->prev_job)
5208                 freejob(jp);
5209         jobless = 0;
5210 }
5211
5212 /* Called after fork(), in parent */
5213 #if !JOBS
5214 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5215 #endif
5216 static void
5217 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5218 {
5219         TRACE(("In parent shell: child = %d\n", pid));
5220         if (!jp) {
5221                 /* jp is NULL when called by openhere() for heredoc support */
5222                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5223                         continue;
5224                 jobless++;
5225                 return;
5226         }
5227 #if JOBS
5228         if (mode != FORK_NOJOB && jp->jobctl) {
5229                 int pgrp;
5230
5231                 if (jp->nprocs == 0)
5232                         pgrp = pid;
5233                 else
5234                         pgrp = jp->ps[0].ps_pid;
5235                 /* This can fail because we are doing it in the child also */
5236                 setpgid(pid, pgrp);
5237         }
5238 #endif
5239         if (mode == FORK_BG) {
5240                 backgndpid = pid;               /* set $! */
5241                 set_curjob(jp, CUR_RUNNING);
5242         }
5243         if (jp) {
5244                 struct procstat *ps = &jp->ps[jp->nprocs++];
5245                 ps->ps_pid = pid;
5246                 ps->ps_status = -1;
5247                 ps->ps_cmd = nullstr;
5248 #if JOBS
5249                 if (doing_jobctl && n)
5250                         ps->ps_cmd = commandtext(n);
5251 #endif
5252         }
5253 }
5254
5255 /* jp and n are NULL when called by openhere() for heredoc support */
5256 static int
5257 forkshell(struct job *jp, union node *n, int mode)
5258 {
5259         int pid;
5260
5261         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5262         pid = fork();
5263         if (pid < 0) {
5264                 TRACE(("Fork failed, errno=%d", errno));
5265                 if (jp)
5266                         freejob(jp);
5267                 ash_msg_and_raise_perror("can't fork");
5268         }
5269         if (pid == 0) {
5270                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5271                 forkchild(jp, n, mode);
5272         } else {
5273                 forkparent(jp, n, mode, pid);
5274         }
5275         return pid;
5276 }
5277
5278 /*
5279  * Wait for job to finish.
5280  *
5281  * Under job control we have the problem that while a child process
5282  * is running interrupts generated by the user are sent to the child
5283  * but not to the shell.  This means that an infinite loop started by
5284  * an interactive user may be hard to kill.  With job control turned off,
5285  * an interactive user may place an interactive program inside a loop.
5286  * If the interactive program catches interrupts, the user doesn't want
5287  * these interrupts to also abort the loop.  The approach we take here
5288  * is to have the shell ignore interrupt signals while waiting for a
5289  * foreground process to terminate, and then send itself an interrupt
5290  * signal if the child process was terminated by an interrupt signal.
5291  * Unfortunately, some programs want to do a bit of cleanup and then
5292  * exit on interrupt; unless these processes terminate themselves by
5293  * sending a signal to themselves (instead of calling exit) they will
5294  * confuse this approach.
5295  *
5296  * Called with interrupts off.
5297  */
5298 static int
5299 waitforjob(struct job *jp)
5300 {
5301         int st;
5302
5303         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5304
5305         INT_OFF;
5306         while (jp->state == JOBRUNNING) {
5307                 /* In non-interactive shells, we _can_ get
5308                  * a keyboard signal here and be EINTRed,
5309                  * but we just loop back, waiting for command to complete.
5310                  *
5311                  * man bash:
5312                  * "If bash is waiting for a command to complete and receives
5313                  * a signal for which a trap has been set, the trap
5314                  * will not be executed until the command completes."
5315                  *
5316                  * Reality is that even if trap is not set, bash
5317                  * will not act on the signal until command completes.
5318                  * Try this. sleep5intoff.c:
5319                  * #include <signal.h>
5320                  * #include <unistd.h>
5321                  * int main() {
5322                  *         sigset_t set;
5323                  *         sigemptyset(&set);
5324                  *         sigaddset(&set, SIGINT);
5325                  *         sigaddset(&set, SIGQUIT);
5326                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5327                  *         sleep(5);
5328                  *         return 0;
5329                  * }
5330                  * $ bash -c './sleep5intoff; echo hi'
5331                  * ^C^C^C^C <--- pressing ^C once a second
5332                  * $ _
5333                  * $ bash -c './sleep5intoff; echo hi'
5334                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5335                  * $ _
5336                  */
5337                 dowait(DOWAIT_BLOCK, jp);
5338         }
5339         INT_ON;
5340
5341         st = getstatus(jp);
5342 #if JOBS
5343         if (jp->jobctl) {
5344                 xtcsetpgrp(ttyfd, rootpid);
5345                 restore_tty_if_stopped_or_signaled(jp);
5346
5347                 /*
5348                  * This is truly gross.
5349                  * If we're doing job control, then we did a TIOCSPGRP which
5350                  * caused us (the shell) to no longer be in the controlling
5351                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5352                  * intuit from the subprocess exit status whether a SIGINT
5353                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5354                  */
5355                 if (jp->sigint) /* TODO: do the same with all signals */
5356                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5357         }
5358         if (jp->state == JOBDONE)
5359 #endif
5360                 freejob(jp);
5361         return st;
5362 }
5363
5364 /*
5365  * return 1 if there are stopped jobs, otherwise 0
5366  */
5367 static int
5368 stoppedjobs(void)
5369 {
5370         struct job *jp;
5371         int retval;
5372
5373         retval = 0;
5374         if (job_warning)
5375                 goto out;
5376         jp = curjob;
5377         if (jp && jp->state == JOBSTOPPED) {
5378                 out2str("You have stopped jobs.\n");
5379                 job_warning = 2;
5380                 retval++;
5381         }
5382  out:
5383         return retval;
5384 }
5385
5386
5387 /*
5388  * Code for dealing with input/output redirection.
5389  */
5390
5391 #undef EMPTY
5392 #undef CLOSED
5393 #define EMPTY -2                /* marks an unused slot in redirtab */
5394 #define CLOSED -1               /* marks a slot of previously-closed fd */
5395
5396 /*
5397  * Handle here documents.  Normally we fork off a process to write the
5398  * data to a pipe.  If the document is short, we can stuff the data in
5399  * the pipe without forking.
5400  */
5401 /* openhere needs this forward reference */
5402 static void expandhere(union node *arg, int fd);
5403 static int
5404 openhere(union node *redir)
5405 {
5406         int pip[2];
5407         size_t len = 0;
5408
5409         if (pipe(pip) < 0)
5410                 ash_msg_and_raise_perror("can't create pipe");
5411         if (redir->type == NHERE) {
5412                 len = strlen(redir->nhere.doc->narg.text);
5413                 if (len <= PIPE_BUF) {
5414                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5415                         goto out;
5416                 }
5417         }
5418         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5419                 /* child */
5420                 close(pip[0]);
5421                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5422                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5423                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5424                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5425                 signal(SIGPIPE, SIG_DFL);
5426                 if (redir->type == NHERE)
5427                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5428                 else /* NXHERE */
5429                         expandhere(redir->nhere.doc, pip[1]);
5430                 _exit(EXIT_SUCCESS);
5431         }
5432  out:
5433         close(pip[1]);
5434         return pip[0];
5435 }
5436
5437 static int
5438 openredirect(union node *redir)
5439 {
5440         struct stat sb;
5441         char *fname;
5442         int f;
5443
5444         switch (redir->nfile.type) {
5445 /* Can't happen, our single caller does this itself */
5446 //      case NTOFD:
5447 //      case NFROMFD:
5448 //              return -1;
5449         case NHERE:
5450         case NXHERE:
5451                 return openhere(redir);
5452         }
5453
5454         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5455          * allocated space. Do it only when we know it is safe.
5456          */
5457         fname = redir->nfile.expfname;
5458
5459         switch (redir->nfile.type) {
5460         default:
5461 #if DEBUG
5462                 abort();
5463 #endif
5464         case NFROM:
5465                 f = open(fname, O_RDONLY);
5466                 if (f < 0)
5467                         goto eopen;
5468                 break;
5469         case NFROMTO:
5470                 f = open(fname, O_RDWR|O_CREAT, 0666);
5471                 if (f < 0)
5472                         goto ecreate;
5473                 break;
5474         case NTO:
5475 #if BASH_REDIR_OUTPUT
5476         case NTO2:
5477 #endif
5478                 /* Take care of noclobber mode. */
5479                 if (Cflag) {
5480                         if (stat(fname, &sb) < 0) {
5481                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5482                                 if (f < 0)
5483                                         goto ecreate;
5484                         } else if (!S_ISREG(sb.st_mode)) {
5485                                 f = open(fname, O_WRONLY, 0666);
5486                                 if (f < 0)
5487                                         goto ecreate;
5488                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5489                                         close(f);
5490                                         errno = EEXIST;
5491                                         goto ecreate;
5492                                 }
5493                         } else {
5494                                 errno = EEXIST;
5495                                 goto ecreate;
5496                         }
5497                         break;
5498                 }
5499                 /* FALLTHROUGH */
5500         case NCLOBBER:
5501                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5502                 if (f < 0)
5503                         goto ecreate;
5504                 break;
5505         case NAPPEND:
5506                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5507                 if (f < 0)
5508                         goto ecreate;
5509                 break;
5510         }
5511
5512         return f;
5513  ecreate:
5514         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5515  eopen:
5516         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5517 }
5518
5519 /*
5520  * Copy a file descriptor to be >= 10. Throws exception on error.
5521  */
5522 static int
5523 savefd(int from)
5524 {
5525         int newfd;
5526         int err;
5527
5528         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5529         err = newfd < 0 ? errno : 0;
5530         if (err != EBADF) {
5531                 if (err)
5532                         ash_msg_and_raise_perror("%d", from);
5533                 close(from);
5534                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5535                         close_on_exec_on(newfd);
5536         }
5537
5538         return newfd;
5539 }
5540 static int
5541 dup2_or_raise(int from, int to)
5542 {
5543         int newfd;
5544
5545         newfd = (from != to) ? dup2(from, to) : to;
5546         if (newfd < 0) {
5547                 /* Happens when source fd is not open: try "echo >&99" */
5548                 ash_msg_and_raise_perror("%d", from);
5549         }
5550         return newfd;
5551 }
5552 static int
5553 dup_CLOEXEC(int fd, int avoid_fd)
5554 {
5555         int newfd;
5556  repeat:
5557         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5558         if (newfd >= 0) {
5559                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5560                         close_on_exec_on(newfd);
5561         } else { /* newfd < 0 */
5562                 if (errno == EBUSY)
5563                         goto repeat;
5564                 if (errno == EINTR)
5565                         goto repeat;
5566         }
5567         return newfd;
5568 }
5569 static int
5570 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5571 {
5572         int newfd;
5573  repeat:
5574         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5575         if (newfd < 0) {
5576                 if (errno == EBUSY)
5577                         goto repeat;
5578                 if (errno == EINTR)
5579                         goto repeat;
5580                 /* fd was not open? */
5581                 if (errno == EBADF)
5582                         return fd;
5583                 ash_msg_and_raise_perror("%d", newfd);
5584         }
5585         if (F_DUPFD_CLOEXEC == F_DUPFD)
5586                 close_on_exec_on(newfd);
5587         close(fd);
5588         return newfd;
5589 }
5590
5591 /* Struct def and variable are moved down to the first usage site */
5592 struct squirrel {
5593         int orig_fd;
5594         int moved_to;
5595 };
5596 struct redirtab {
5597         struct redirtab *next;
5598         int pair_count;
5599         struct squirrel two_fd[];
5600 };
5601 #define redirlist (G_var.redirlist)
5602
5603 static void
5604 add_squirrel_closed(struct redirtab *sq, int fd)
5605 {
5606         int i;
5607
5608         if (!sq)
5609                 return;
5610
5611         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5612                 /* If we collide with an already moved fd... */
5613                 if (fd == sq->two_fd[i].orig_fd) {
5614                         /* Examples:
5615                          * "echo 3>FILE 3>&- 3>FILE"
5616                          * "echo 3>&- 3>FILE"
5617                          * No need for last redirect to insert
5618                          * another "need to close 3" indicator.
5619                          */
5620                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5621                         return;
5622                 }
5623         }
5624         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5625         sq->two_fd[i].orig_fd = fd;
5626         sq->two_fd[i].moved_to = CLOSED;
5627 }
5628
5629 static int
5630 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5631 {
5632         int i, new_fd;
5633
5634         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5635                 avoid_fd = 9;
5636
5637 #if JOBS
5638         if (fd == ttyfd) {
5639                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5640                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5641                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5642                 return 1; /* "we closed fd" */
5643         }
5644 #endif
5645         /* Are we called from redirect(0)? E.g. redirect
5646          * in a forked child. No need to save fds,
5647          * we aren't going to use them anymore, ok to trash.
5648          */
5649         if (!sq)
5650                 return 0;
5651
5652         /* If this one of script's fds? */
5653         if (fd != 0) {
5654                 struct parsefile *pf = g_parsefile;
5655                 while (pf) {
5656                         /* We skip fd == 0 case because of the following:
5657                          * $ ash  # running ash interactively
5658                          * $ . ./script.sh
5659                          * and in script.sh: "exec 9>&0".
5660                          * Even though top-level pf_fd _is_ 0,
5661                          * it's still ok to use it: "read" builtin uses it,
5662                          * why should we cripple "exec" builtin?
5663                          */
5664                         if (fd == pf->pf_fd) {
5665                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5666                                 return 1; /* "we closed fd" */
5667                         }
5668                         pf = pf->prev;
5669                 }
5670         }
5671
5672         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5673
5674         /* First: do we collide with some already moved fds? */
5675         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5676                 /* If we collide with an already moved fd... */
5677                 if (fd == sq->two_fd[i].moved_to) {
5678                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5679                         sq->two_fd[i].moved_to = new_fd;
5680                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5681                         if (new_fd < 0) /* what? */
5682                                 xfunc_die();
5683                         return 0; /* "we did not close fd" */
5684                 }
5685                 if (fd == sq->two_fd[i].orig_fd) {
5686                         /* Example: echo Hello >/dev/null 1>&2 */
5687                         TRACE(("redirect_fd %d: already moved\n", fd));
5688                         return 0; /* "we did not close fd" */
5689                 }
5690         }
5691
5692         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5693         new_fd = dup_CLOEXEC(fd, avoid_fd);
5694         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5695         if (new_fd < 0) {
5696                 if (errno != EBADF)
5697                         xfunc_die();
5698                 /* new_fd = CLOSED; - already is -1 */
5699         }
5700         sq->two_fd[i].moved_to = new_fd;
5701         sq->two_fd[i].orig_fd = fd;
5702
5703         /* if we move stderr, let "set -x" code know */
5704         if (fd == preverrout_fd)
5705                 preverrout_fd = new_fd;
5706
5707         return 0; /* "we did not close fd" */
5708 }
5709
5710 static int
5711 internally_opened_fd(int fd, struct redirtab *sq)
5712 {
5713         int i;
5714 #if JOBS
5715         if (fd == ttyfd)
5716                 return 1;
5717 #endif
5718         /* If this one of script's fds? */
5719         if (fd != 0) {
5720                 struct parsefile *pf = g_parsefile;
5721                 while (pf) {
5722                         if (fd == pf->pf_fd)
5723                                 return 1;
5724                         pf = pf->prev;
5725                 }
5726         }
5727
5728         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5729                 if (fd == sq->two_fd[i].moved_to)
5730                         return 1;
5731         }
5732         return 0;
5733 }
5734
5735 /*
5736  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5737  * old file descriptors are stashed away so that the redirection can be
5738  * undone by calling popredir.
5739  */
5740 /* flags passed to redirect */
5741 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5742 static void
5743 redirect(union node *redir, int flags)
5744 {
5745         struct redirtab *sv;
5746
5747         if (!redir)
5748                 return;
5749
5750         sv = NULL;
5751         INT_OFF;
5752         if (flags & REDIR_PUSH)
5753                 sv = redirlist;
5754         do {
5755                 int fd;
5756                 int newfd;
5757                 int close_fd;
5758                 int closed;
5759
5760                 fd = redir->nfile.fd;
5761                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5762                         //bb_error_msg("doing %d > %d", fd, newfd);
5763                         newfd = redir->ndup.dupfd;
5764                         close_fd = -1;
5765                 } else {
5766                         newfd = openredirect(redir); /* always >= 0 */
5767                         if (fd == newfd) {
5768                                 /* open() gave us precisely the fd we wanted.
5769                                  * This means that this fd was not busy
5770                                  * (not opened to anywhere).
5771                                  * Remember to close it on restore:
5772                                  */
5773                                 add_squirrel_closed(sv, fd);
5774                                 continue;
5775                         }
5776                         close_fd = newfd;
5777                 }
5778
5779                 if (fd == newfd)
5780                         continue;
5781
5782                 /* if "N>FILE": move newfd to fd */
5783                 /* if "N>&M": dup newfd to fd */
5784                 /* if "N>&-": close fd (newfd is -1) */
5785
5786  IF_BASH_REDIR_OUTPUT(redirect_more:)
5787
5788                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5789                 if (newfd == -1) {
5790                         /* "N>&-" means "close me" */
5791                         if (!closed) {
5792                                 /* ^^^ optimization: saving may already
5793                                  * have closed it. If not... */
5794                                 close(fd);
5795                         }
5796                 } else {
5797                         /* if newfd is a script fd or saved fd, simulate EBADF */
5798                         if (internally_opened_fd(newfd, sv)) {
5799                                 errno = EBADF;
5800                                 ash_msg_and_raise_perror("%d", newfd);
5801                         }
5802                         dup2_or_raise(newfd, fd);
5803                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5804                                 close(close_fd);
5805 #if BASH_REDIR_OUTPUT
5806                         if (redir->nfile.type == NTO2 && fd == 1) {
5807                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5808                                 fd = 2;
5809                                 newfd = 1;
5810                                 close_fd = -1;
5811                                 goto redirect_more;
5812                         }
5813 #endif
5814                 }
5815         } while ((redir = redir->nfile.next) != NULL);
5816         INT_ON;
5817
5818 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5819 #define REDIR_SAVEFD2 0
5820         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5821         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5822         // not only for calls with flags containing REDIR_SAVEFD2.
5823         // We do this unconditionally (see save_fd_on_redirect()).
5824         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5825         //      preverrout_fd = copied_fd2;
5826 }
5827
5828 static int
5829 redirectsafe(union node *redir, int flags)
5830 {
5831         int err;
5832         volatile int saveint;
5833         struct jmploc *volatile savehandler = exception_handler;
5834         struct jmploc jmploc;
5835
5836         SAVE_INT(saveint);
5837         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5838         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5839         if (!err) {
5840                 exception_handler = &jmploc;
5841                 redirect(redir, flags);
5842         }
5843         exception_handler = savehandler;
5844         if (err && exception_type != EXERROR)
5845                 longjmp(exception_handler->loc, 1);
5846         RESTORE_INT(saveint);
5847         return err;
5848 }
5849
5850 static struct redirtab*
5851 pushredir(union node *redir)
5852 {
5853         struct redirtab *sv;
5854         int i;
5855
5856         if (!redir)
5857                 return redirlist;
5858
5859         i = 0;
5860         do {
5861                 i++;
5862 #if BASH_REDIR_OUTPUT
5863                 if (redir->nfile.type == NTO2)
5864                         i++;
5865 #endif
5866                 redir = redir->nfile.next;
5867         } while (redir);
5868
5869         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5870         sv->pair_count = i;
5871         while (--i >= 0)
5872                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5873         sv->next = redirlist;
5874         redirlist = sv;
5875         return sv->next;
5876 }
5877
5878 /*
5879  * Undo the effects of the last redirection.
5880  */
5881 static void
5882 popredir(int drop)
5883 {
5884         struct redirtab *rp;
5885         int i;
5886
5887         if (redirlist == NULL)
5888                 return;
5889         INT_OFF;
5890         rp = redirlist;
5891         for (i = 0; i < rp->pair_count; i++) {
5892                 int fd = rp->two_fd[i].orig_fd;
5893                 int copy = rp->two_fd[i].moved_to;
5894                 if (copy == CLOSED) {
5895                         if (!drop)
5896                                 close(fd);
5897                         continue;
5898                 }
5899                 if (copy != EMPTY) {
5900                         if (!drop) {
5901                                 /*close(fd);*/
5902                                 dup2_or_raise(copy, fd);
5903                         }
5904                         close(copy);
5905                 }
5906         }
5907         redirlist = rp->next;
5908         free(rp);
5909         INT_ON;
5910 }
5911
5912 static void
5913 unwindredir(struct redirtab *stop)
5914 {
5915         while (redirlist != stop)
5916                 popredir(/*drop:*/ 0);
5917 }
5918
5919
5920 /* ============ Routines to expand arguments to commands
5921  *
5922  * We have to deal with backquotes, shell variables, and file metacharacters.
5923  */
5924
5925 #if ENABLE_FEATURE_SH_MATH
5926 static arith_t
5927 ash_arith(const char *s)
5928 {
5929         arith_state_t math_state;
5930         arith_t result;
5931
5932         math_state.lookupvar = lookupvar;
5933         math_state.setvar    = setvar0;
5934         //math_state.endofname = endofname;
5935
5936         INT_OFF;
5937         result = arith(&math_state, s);
5938         if (math_state.errmsg)
5939                 ash_msg_and_raise_error(math_state.errmsg);
5940         INT_ON;
5941
5942         return result;
5943 }
5944 #endif
5945 #if BASH_SUBSTR
5946 # if ENABLE_FEATURE_SH_MATH
5947 static int substr_atoi(const char *s)
5948 {
5949         arith_t t = ash_arith(s);
5950         if (sizeof(t) > sizeof(int)) {
5951                 /* clamp very large or very large negative nums for ${v:N:M}:
5952                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5953                  */
5954                 if (t > INT_MAX)
5955                         t = INT_MAX;
5956                 if (t < INT_MIN)
5957                         t = INT_MIN;
5958         }
5959         return t;
5960 }
5961 # else
5962 #  define substr_atoi(s) number(s)
5963 # endif
5964 #endif
5965
5966 /*
5967  * expandarg flags
5968  */
5969 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5970 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5971 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5972 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5973 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5974  * POSIX says for this case:
5975  *  Pathname expansion shall not be performed on the word by a
5976  *  non-interactive shell; an interactive shell may perform it, but shall
5977  *  do so only when the expansion would result in one word.
5978  * Currently, our code complies to the above rule by never globbing
5979  * redirection filenames.
5980  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5981  * (this means that on a typical Linux distro, bash almost always
5982  * performs globbing, and thus diverges from what we do).
5983  */
5984 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5985 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5986 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5987 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5988 /*
5989  * rmescape() flags
5990  */
5991 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5992 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5993 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5994 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5995
5996 /* Add CTLESC when necessary. */
5997 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5998 /* Do not skip NUL characters. */
5999 #define QUOTES_KEEPNUL EXP_TILDE
6000
6001 /*
6002  * Structure specifying which parts of the string should be searched
6003  * for IFS characters.
6004  */
6005 struct ifsregion {
6006         struct ifsregion *next; /* next region in list */
6007         int begoff;             /* offset of start of region */
6008         int endoff;             /* offset of end of region */
6009         int nulonly;            /* search for nul bytes only */
6010 };
6011
6012 struct arglist {
6013         struct strlist *list;
6014         struct strlist **lastp;
6015 };
6016
6017 /* output of current string */
6018 static char *expdest;
6019 /* list of back quote expressions */
6020 static struct nodelist *argbackq;
6021 /* first struct in list of ifs regions */
6022 static struct ifsregion ifsfirst;
6023 /* last struct in list */
6024 static struct ifsregion *ifslastp;
6025 /* holds expanded arg list */
6026 static struct arglist exparg;
6027
6028 /*
6029  * Our own itoa().
6030  * cvtnum() is used even if math support is off (to prepare $? values and such).
6031  */
6032 static int
6033 cvtnum(arith_t num)
6034 {
6035         int len;
6036
6037         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6038         len = sizeof(arith_t) * 3;
6039         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6040         if (sizeof(arith_t) < 4) len += 2;
6041
6042         expdest = makestrspace(len, expdest);
6043         len = fmtstr(expdest, len, ARITH_FMT, num);
6044         STADJUST(len, expdest);
6045         return len;
6046 }
6047
6048 /*
6049  * Break the argument string into pieces based upon IFS and add the
6050  * strings to the argument list.  The regions of the string to be
6051  * searched for IFS characters have been stored by recordregion.
6052  */
6053 static void
6054 ifsbreakup(char *string, struct arglist *arglist)
6055 {
6056         struct ifsregion *ifsp;
6057         struct strlist *sp;
6058         char *start;
6059         char *p;
6060         char *q;
6061         const char *ifs, *realifs;
6062         int ifsspc;
6063         int nulonly;
6064
6065         start = string;
6066         if (ifslastp != NULL) {
6067                 ifsspc = 0;
6068                 nulonly = 0;
6069                 realifs = ifsset() ? ifsval() : defifs;
6070                 ifsp = &ifsfirst;
6071                 do {
6072                         int afternul;
6073
6074                         p = string + ifsp->begoff;
6075                         afternul = nulonly;
6076                         nulonly = ifsp->nulonly;
6077                         ifs = nulonly ? nullstr : realifs;
6078                         ifsspc = 0;
6079                         while (p < string + ifsp->endoff) {
6080                                 q = p;
6081                                 if ((unsigned char)*p == CTLESC)
6082                                         p++;
6083                                 if (!strchr(ifs, *p)) {
6084                                         p++;
6085                                         continue;
6086                                 }
6087                                 if (!(afternul || nulonly))
6088                                         ifsspc = (strchr(defifs, *p) != NULL);
6089                                 /* Ignore IFS whitespace at start */
6090                                 if (q == start && ifsspc) {
6091                                         p++;
6092                                         start = p;
6093                                         continue;
6094                                 }
6095                                 *q = '\0';
6096                                 sp = stzalloc(sizeof(*sp));
6097                                 sp->text = start;
6098                                 *arglist->lastp = sp;
6099                                 arglist->lastp = &sp->next;
6100                                 p++;
6101                                 if (!nulonly) {
6102                                         for (;;) {
6103                                                 if (p >= string + ifsp->endoff) {
6104                                                         break;
6105                                                 }
6106                                                 q = p;
6107                                                 if ((unsigned char)*p == CTLESC)
6108                                                         p++;
6109                                                 if (strchr(ifs, *p) == NULL) {
6110                                                         p = q;
6111                                                         break;
6112                                                 }
6113                                                 if (strchr(defifs, *p) == NULL) {
6114                                                         if (ifsspc) {
6115                                                                 p++;
6116                                                                 ifsspc = 0;
6117                                                         } else {
6118                                                                 p = q;
6119                                                                 break;
6120                                                         }
6121                                                 } else
6122                                                         p++;
6123                                         }
6124                                 }
6125                                 start = p;
6126                         } /* while */
6127                         ifsp = ifsp->next;
6128                 } while (ifsp != NULL);
6129                 if (nulonly)
6130                         goto add;
6131         }
6132
6133         if (!*start)
6134                 return;
6135
6136  add:
6137         sp = stzalloc(sizeof(*sp));
6138         sp->text = start;
6139         *arglist->lastp = sp;
6140         arglist->lastp = &sp->next;
6141 }
6142
6143 static void
6144 ifsfree(void)
6145 {
6146         struct ifsregion *p = ifsfirst.next;
6147
6148         if (!p)
6149                 goto out;
6150
6151         INT_OFF;
6152         do {
6153                 struct ifsregion *ifsp;
6154                 ifsp = p->next;
6155                 free(p);
6156                 p = ifsp;
6157         } while (p);
6158         ifsfirst.next = NULL;
6159         INT_ON;
6160  out:
6161         ifslastp = NULL;
6162 }
6163
6164 static size_t
6165 esclen(const char *start, const char *p)
6166 {
6167         size_t esc = 0;
6168
6169         while (p > start && (unsigned char)*--p == CTLESC) {
6170                 esc++;
6171         }
6172         return esc;
6173 }
6174
6175 /*
6176  * Remove any CTLESC characters from a string.
6177  */
6178 #if !BASH_PATTERN_SUBST
6179 #define rmescapes(str, flag, slash_position) \
6180         rmescapes(str, flag)
6181 #endif
6182 static char *
6183 rmescapes(char *str, int flag, int *slash_position)
6184 {
6185         static const char qchars[] ALIGN1 = {
6186                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6187
6188         char *p, *q, *r;
6189         unsigned protect_against_glob;
6190         unsigned globbing;
6191
6192         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6193         if (!p)
6194                 return str;
6195
6196         q = p;
6197         r = str;
6198         if (flag & RMESCAPE_ALLOC) {
6199                 size_t len = p - str;
6200                 size_t fulllen = len + strlen(p) + 1;
6201
6202                 if (flag & RMESCAPE_GROW) {
6203                         int strloc = str - (char *)stackblock();
6204                         r = makestrspace(fulllen, expdest);
6205                         /* p and str may be invalidated by makestrspace */
6206                         str = (char *)stackblock() + strloc;
6207                         p = str + len;
6208                 } else if (flag & RMESCAPE_HEAP) {
6209                         r = ckmalloc(fulllen);
6210                 } else {
6211                         r = stalloc(fulllen);
6212                 }
6213                 q = r;
6214                 if (len > 0) {
6215                         q = (char *)mempcpy(q, str, len);
6216                 }
6217         }
6218
6219         globbing = flag & RMESCAPE_GLOB;
6220         protect_against_glob = globbing;
6221         while (*p) {
6222                 if ((unsigned char)*p == CTLQUOTEMARK) {
6223 // Note: protect_against_glob only affect whether
6224 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6225                         p++;
6226                         protect_against_glob = globbing;
6227                         continue;
6228                 }
6229                 if (*p == '\\') {
6230                         /* naked back slash */
6231                         protect_against_glob = 0;
6232                         goto copy;
6233                 }
6234                 if ((unsigned char)*p == CTLESC) {
6235                         p++;
6236 #if DEBUG
6237                         if (*p == '\0')
6238                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6239 #endif
6240                         if (protect_against_glob) {
6241                                 /*
6242                                  * We used to trust glob() and fnmatch() to eat
6243                                  * superfluous escapes (\z where z has no
6244                                  * special meaning anyway). But this causes
6245                                  * bugs such as string of one greek letter rho
6246                                  * (unicode-encoded as two bytes "cf,81")
6247                                  * getting encoded as "cf,CTLESC,81"
6248                                  * and here, converted to "cf,\,81" -
6249                                  * which does not go well with some flavors
6250                                  * of fnmatch() in unicode locales
6251                                  * (for example, glibc <= 2.22).
6252                                  *
6253                                  * Lets add "\" only on the chars which need it.
6254                                  * Testcases for less obvious chars are shown.
6255                                  */
6256                                 if (*p == '*'
6257                                  || *p == '?'
6258                                  || *p == '['
6259                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6260                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6261                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6262                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6263                                 /* Some libc support [^negate], that's why "^" also needs love */
6264                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6265                                 ) {
6266                                         *q++ = '\\';
6267                                 }
6268                         }
6269                 }
6270 #if BASH_PATTERN_SUBST
6271                 else if (slash_position && p == str + *slash_position) {
6272                         /* stop handling globbing */
6273                         globbing = 0;
6274                         *slash_position = q - r;
6275                         slash_position = NULL;
6276                 }
6277 #endif
6278                 protect_against_glob = globbing;
6279  copy:
6280                 *q++ = *p++;
6281         }
6282         *q = '\0';
6283         if (flag & RMESCAPE_GROW) {
6284                 expdest = r;
6285                 STADJUST(q - r + 1, expdest);
6286         }
6287         return r;
6288 }
6289 #define pmatch(a, b) !fnmatch((a), (b), 0)
6290
6291 /*
6292  * Prepare a pattern for a expmeta (internal glob(3)) call.
6293  *
6294  * Returns an stalloced string.
6295  */
6296 static char *
6297 preglob(const char *pattern, int flag)
6298 {
6299         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6300 }
6301
6302 /*
6303  * Put a string on the stack.
6304  */
6305 static void
6306 memtodest(const char *p, size_t len, int syntax, int quotes)
6307 {
6308         char *q;
6309
6310         if (!len)
6311                 return;
6312
6313         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6314
6315         do {
6316                 unsigned char c = *p++;
6317                 if (c) {
6318                         if (quotes & QUOTES_ESC) {
6319                                 int n = SIT(c, syntax);
6320                                 if (n == CCTL
6321                                  || (syntax != BASESYNTAX && n == CBACK)
6322                                 ) {
6323                                         USTPUTC(CTLESC, q);
6324                                 }
6325                         }
6326                 } else if (!(quotes & QUOTES_KEEPNUL))
6327                         continue;
6328                 USTPUTC(c, q);
6329         } while (--len);
6330
6331         expdest = q;
6332 }
6333
6334 static size_t
6335 strtodest(const char *p, int syntax, int quotes)
6336 {
6337         size_t len = strlen(p);
6338         memtodest(p, len, syntax, quotes);
6339         return len;
6340 }
6341
6342 /*
6343  * Record the fact that we have to scan this region of the
6344  * string for IFS characters.
6345  */
6346 static void
6347 recordregion(int start, int end, int nulonly)
6348 {
6349         struct ifsregion *ifsp;
6350
6351         if (ifslastp == NULL) {
6352                 ifsp = &ifsfirst;
6353         } else {
6354                 INT_OFF;
6355                 ifsp = ckzalloc(sizeof(*ifsp));
6356                 /*ifsp->next = NULL; - ckzalloc did it */
6357                 ifslastp->next = ifsp;
6358                 INT_ON;
6359         }
6360         ifslastp = ifsp;
6361         ifslastp->begoff = start;
6362         ifslastp->endoff = end;
6363         ifslastp->nulonly = nulonly;
6364 }
6365
6366 static void
6367 removerecordregions(int endoff)
6368 {
6369         if (ifslastp == NULL)
6370                 return;
6371
6372         if (ifsfirst.endoff > endoff) {
6373                 while (ifsfirst.next) {
6374                         struct ifsregion *ifsp;
6375                         INT_OFF;
6376                         ifsp = ifsfirst.next->next;
6377                         free(ifsfirst.next);
6378                         ifsfirst.next = ifsp;
6379                         INT_ON;
6380                 }
6381                 if (ifsfirst.begoff > endoff) {
6382                         ifslastp = NULL;
6383                 } else {
6384                         ifslastp = &ifsfirst;
6385                         ifsfirst.endoff = endoff;
6386                 }
6387                 return;
6388         }
6389
6390         ifslastp = &ifsfirst;
6391         while (ifslastp->next && ifslastp->next->begoff < endoff)
6392                 ifslastp = ifslastp->next;
6393         while (ifslastp->next) {
6394                 struct ifsregion *ifsp;
6395                 INT_OFF;
6396                 ifsp = ifslastp->next->next;
6397                 free(ifslastp->next);
6398                 ifslastp->next = ifsp;
6399                 INT_ON;
6400         }
6401         if (ifslastp->endoff > endoff)
6402                 ifslastp->endoff = endoff;
6403 }
6404
6405 static char *
6406 exptilde(char *startp, char *p, int flags)
6407 {
6408         unsigned char c;
6409         char *name;
6410         struct passwd *pw;
6411         const char *home;
6412         int quotes = flags & QUOTES_ESC;
6413
6414         name = p + 1;
6415
6416         while ((c = *++p) != '\0') {
6417                 switch (c) {
6418                 case CTLESC:
6419                         return startp;
6420                 case CTLQUOTEMARK:
6421                         return startp;
6422                 case ':':
6423                         if (flags & EXP_VARTILDE)
6424                                 goto done;
6425                         break;
6426                 case '/':
6427                 case CTLENDVAR:
6428                         goto done;
6429                 }
6430         }
6431  done:
6432         *p = '\0';
6433         if (*name == '\0') {
6434                 home = lookupvar("HOME");
6435         } else {
6436                 pw = getpwnam(name);
6437                 if (pw == NULL)
6438                         goto lose;
6439                 home = pw->pw_dir;
6440         }
6441         if (!home || !*home)
6442                 goto lose;
6443         *p = c;
6444         strtodest(home, SQSYNTAX, quotes);
6445         return p;
6446  lose:
6447         *p = c;
6448         return startp;
6449 }
6450
6451 /*
6452  * Execute a command inside back quotes.  If it's a builtin command, we
6453  * want to save its output in a block obtained from malloc.  Otherwise
6454  * we fork off a subprocess and get the output of the command via a pipe.
6455  * Should be called with interrupts off.
6456  */
6457 struct backcmd {                /* result of evalbackcmd */
6458         int fd;                 /* file descriptor to read from */
6459         int nleft;              /* number of chars in buffer */
6460         char *buf;              /* buffer */
6461         struct job *jp;         /* job structure for command */
6462 };
6463
6464 /* These forward decls are needed to use "eval" code for backticks handling: */
6465 /* flags in argument to evaltree */
6466 #define EV_EXIT    01           /* exit after evaluating tree */
6467 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6468 static int evaltree(union node *, int);
6469
6470 /* An evaltree() which is known to never return.
6471  * Used to use an alias:
6472  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6473  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6474  */
6475 static ALWAYS_INLINE NORETURN void
6476 evaltreenr(union node *n, int flags)
6477 {
6478         evaltree(n, flags);
6479         bb_unreachable(abort());
6480         /* NOTREACHED */
6481 }
6482
6483 static void FAST_FUNC
6484 evalbackcmd(union node *n, struct backcmd *result)
6485 {
6486         int pip[2];
6487         struct job *jp;
6488
6489         result->fd = -1;
6490         result->buf = NULL;
6491         result->nleft = 0;
6492         result->jp = NULL;
6493         if (n == NULL) {
6494                 goto out;
6495         }
6496
6497         if (pipe(pip) < 0)
6498                 ash_msg_and_raise_perror("can't create pipe");
6499         jp = makejob(/*n,*/ 1);
6500         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6501                 /* child */
6502                 FORCE_INT_ON;
6503                 close(pip[0]);
6504                 if (pip[1] != 1) {
6505                         /*close(1);*/
6506                         dup2_or_raise(pip[1], 1);
6507                         close(pip[1]);
6508                 }
6509 /* TODO: eflag clearing makes the following not abort:
6510  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6511  * which is what bash does (unless it is in POSIX mode).
6512  * dash deleted "eflag = 0" line in the commit
6513  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6514  *  [EVAL] Don't clear eflag in evalbackcmd
6515  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6516  */
6517                 eflag = 0;
6518                 ifsfree();
6519                 evaltreenr(n, EV_EXIT);
6520                 /* NOTREACHED */
6521         }
6522         /* parent */
6523         close(pip[1]);
6524         result->fd = pip[0];
6525         result->jp = jp;
6526
6527  out:
6528         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6529                 result->fd, result->buf, result->nleft, result->jp));
6530 }
6531
6532 /*
6533  * Expand stuff in backwards quotes.
6534  */
6535 static void
6536 expbackq(union node *cmd, int flag)
6537 {
6538         struct backcmd in;
6539         int i;
6540         char buf[128];
6541         char *p;
6542         char *dest;
6543         int startloc;
6544         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6545         struct stackmark smark;
6546
6547         INT_OFF;
6548         startloc = expdest - (char *)stackblock();
6549         pushstackmark(&smark, startloc);
6550         evalbackcmd(cmd, &in);
6551         popstackmark(&smark);
6552
6553         p = in.buf;
6554         i = in.nleft;
6555         if (i == 0)
6556                 goto read;
6557         for (;;) {
6558                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6559  read:
6560                 if (in.fd < 0)
6561                         break;
6562                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6563                 TRACE(("expbackq: read returns %d\n", i));
6564                 if (i <= 0)
6565                         break;
6566                 p = buf;
6567         }
6568
6569         free(in.buf);
6570         if (in.fd >= 0) {
6571                 close(in.fd);
6572                 back_exitstatus = waitforjob(in.jp);
6573         }
6574         INT_ON;
6575
6576         /* Eat all trailing newlines */
6577         dest = expdest;
6578         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6579                 STUNPUTC(dest);
6580         expdest = dest;
6581
6582         if (!(flag & EXP_QUOTED))
6583                 recordregion(startloc, dest - (char *)stackblock(), 0);
6584         TRACE(("evalbackq: size:%d:'%.*s'\n",
6585                 (int)((dest - (char *)stackblock()) - startloc),
6586                 (int)((dest - (char *)stackblock()) - startloc),
6587                 stackblock() + startloc));
6588 }
6589
6590 #if ENABLE_FEATURE_SH_MATH
6591 /*
6592  * Expand arithmetic expression.  Backup to start of expression,
6593  * evaluate, place result in (backed up) result, adjust string position.
6594  */
6595 static void
6596 expari(int flag)
6597 {
6598         char *p, *start;
6599         int begoff;
6600         int len;
6601
6602         /* ifsfree(); */
6603
6604         /*
6605          * This routine is slightly over-complicated for
6606          * efficiency.  Next we scan backwards looking for the
6607          * start of arithmetic.
6608          */
6609         start = stackblock();
6610         p = expdest - 1;
6611         *p = '\0';
6612         p--;
6613         while (1) {
6614                 int esc;
6615
6616                 while ((unsigned char)*p != CTLARI) {
6617                         p--;
6618 #if DEBUG
6619                         if (p < start) {
6620                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6621                         }
6622 #endif
6623                 }
6624
6625                 esc = esclen(start, p);
6626                 if (!(esc % 2)) {
6627                         break;
6628                 }
6629
6630                 p -= esc + 1;
6631         }
6632
6633         begoff = p - start;
6634
6635         removerecordregions(begoff);
6636
6637         expdest = p;
6638
6639         if (flag & QUOTES_ESC)
6640                 rmescapes(p + 1, 0, NULL);
6641
6642         len = cvtnum(ash_arith(p + 1));
6643
6644         if (!(flag & EXP_QUOTED))
6645                 recordregion(begoff, begoff + len, 0);
6646 }
6647 #endif
6648
6649 /* argstr needs it */
6650 static char *evalvar(char *p, int flags);
6651
6652 /*
6653  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6654  * characters to allow for further processing.  Otherwise treat
6655  * $@ like $* since no splitting will be performed.
6656  */
6657 static void
6658 argstr(char *p, int flags)
6659 {
6660         static const char spclchars[] ALIGN1 = {
6661                 '=',
6662                 ':',
6663                 CTLQUOTEMARK,
6664                 CTLENDVAR,
6665                 CTLESC,
6666                 CTLVAR,
6667                 CTLBACKQ,
6668 #if ENABLE_FEATURE_SH_MATH
6669                 CTLENDARI,
6670 #endif
6671                 '\0'
6672         };
6673         const char *reject = spclchars;
6674         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6675         int inquotes;
6676         size_t length;
6677         int startloc;
6678
6679         if (!(flags & EXP_VARTILDE)) {
6680                 reject += 2;
6681         } else if (flags & EXP_VARTILDE2) {
6682                 reject++;
6683         }
6684         inquotes = 0;
6685         length = 0;
6686         if (flags & EXP_TILDE) {
6687                 char *q;
6688
6689                 flags &= ~EXP_TILDE;
6690  tilde:
6691                 q = p;
6692                 if (*q == '~')
6693                         p = exptilde(p, q, flags);
6694         }
6695  start:
6696         startloc = expdest - (char *)stackblock();
6697         for (;;) {
6698                 unsigned char c;
6699
6700                 length += strcspn(p + length, reject);
6701                 c = p[length];
6702                 if (c) {
6703                         if (!(c & 0x80)
6704                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6705                         ) {
6706                                 /* c == '=' || c == ':' || c == CTLENDARI */
6707                                 length++;
6708                         }
6709                 }
6710                 if (length > 0) {
6711                         int newloc;
6712                         expdest = stack_nputstr(p, length, expdest);
6713                         newloc = expdest - (char *)stackblock();
6714                         if (breakall && !inquotes && newloc > startloc) {
6715                                 recordregion(startloc, newloc, 0);
6716                         }
6717                         startloc = newloc;
6718                 }
6719                 p += length + 1;
6720                 length = 0;
6721
6722                 switch (c) {
6723                 case '\0':
6724                         goto breakloop;
6725                 case '=':
6726                         if (flags & EXP_VARTILDE2) {
6727                                 p--;
6728                                 continue;
6729                         }
6730                         flags |= EXP_VARTILDE2;
6731                         reject++;
6732                         /* fall through */
6733                 case ':':
6734                         /*
6735                          * sort of a hack - expand tildes in variable
6736                          * assignments (after the first '=' and after ':'s).
6737                          */
6738                         if (*--p == '~') {
6739                                 goto tilde;
6740                         }
6741                         continue;
6742                 }
6743
6744                 switch (c) {
6745                 case CTLENDVAR: /* ??? */
6746                         goto breakloop;
6747                 case CTLQUOTEMARK:
6748                         /* "$@" syntax adherence hack */
6749                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6750                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6751                                 goto start;
6752                         }
6753                         inquotes ^= EXP_QUOTED;
6754  addquote:
6755                         if (flags & QUOTES_ESC) {
6756                                 p--;
6757                                 length++;
6758                                 startloc++;
6759                         }
6760                         break;
6761                 case CTLESC:
6762                         startloc++;
6763                         length++;
6764                         goto addquote;
6765                 case CTLVAR:
6766                         TRACE(("argstr: evalvar('%s')\n", p));
6767                         p = evalvar(p, flags | inquotes);
6768                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6769                         goto start;
6770                 case CTLBACKQ:
6771                         expbackq(argbackq->n, flags | inquotes);
6772                         argbackq = argbackq->next;
6773                         goto start;
6774 #if ENABLE_FEATURE_SH_MATH
6775                 case CTLENDARI:
6776                         p--;
6777                         expari(flags | inquotes);
6778                         goto start;
6779 #endif
6780                 }
6781         }
6782  breakloop: ;
6783 }
6784
6785 static char *
6786 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6787                 char *pattern, int quotes, int zero)
6788 {
6789         char *loc, *loc2;
6790         char c;
6791
6792         loc = startp;
6793         loc2 = rmesc;
6794         do {
6795                 int match;
6796                 const char *s = loc2;
6797
6798                 c = *loc2;
6799                 if (zero) {
6800                         *loc2 = '\0';
6801                         s = rmesc;
6802                 }
6803                 match = pmatch(pattern, s);
6804
6805                 *loc2 = c;
6806                 if (match)
6807                         return loc;
6808                 if (quotes && (unsigned char)*loc == CTLESC)
6809                         loc++;
6810                 loc++;
6811                 loc2++;
6812         } while (c);
6813         return NULL;
6814 }
6815
6816 static char *
6817 scanright(char *startp, char *rmesc, char *rmescend,
6818                 char *pattern, int quotes, int match_at_start)
6819 {
6820 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6821         int try2optimize = match_at_start;
6822 #endif
6823         int esc = 0;
6824         char *loc;
6825         char *loc2;
6826
6827         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6828          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6829          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6830          * Logic:
6831          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6832          * and on each iteration they go back two/one char until they reach the beginning.
6833          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6834          */
6835         /* TODO: document in what other circumstances we are called. */
6836
6837         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6838                 int match;
6839                 char c = *loc2;
6840                 const char *s = loc2;
6841                 if (match_at_start) {
6842                         *loc2 = '\0';
6843                         s = rmesc;
6844                 }
6845                 match = pmatch(pattern, s);
6846                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6847                 *loc2 = c;
6848                 if (match)
6849                         return loc;
6850 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6851                 if (try2optimize) {
6852                         /* Maybe we can optimize this:
6853                          * if pattern ends with unescaped *, we can avoid checking
6854                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6855                          * it won't match truncated "raw_value_of_" strings too.
6856                          */
6857                         unsigned plen = strlen(pattern);
6858                         /* Does it end with "*"? */
6859                         if (plen != 0 && pattern[--plen] == '*') {
6860                                 /* "xxxx*" is not escaped */
6861                                 /* "xxx\*" is escaped */
6862                                 /* "xx\\*" is not escaped */
6863                                 /* "x\\\*" is escaped */
6864                                 int slashes = 0;
6865                                 while (plen != 0 && pattern[--plen] == '\\')
6866                                         slashes++;
6867                                 if (!(slashes & 1))
6868                                         break; /* ends with unescaped "*" */
6869                         }
6870                         try2optimize = 0;
6871                 }
6872 #endif
6873                 loc--;
6874                 if (quotes) {
6875                         if (--esc < 0) {
6876                                 esc = esclen(startp, loc);
6877                         }
6878                         if (esc % 2) {
6879                                 esc--;
6880                                 loc--;
6881                         }
6882                 }
6883         }
6884         return NULL;
6885 }
6886
6887 static void varunset(const char *, const char *, const char *, int) NORETURN;
6888 static void
6889 varunset(const char *end, const char *var, const char *umsg, int varflags)
6890 {
6891         const char *msg;
6892         const char *tail;
6893
6894         tail = nullstr;
6895         msg = "parameter not set";
6896         if (umsg) {
6897                 if ((unsigned char)*end == CTLENDVAR) {
6898                         if (varflags & VSNUL)
6899                                 tail = " or null";
6900                 } else {
6901                         msg = umsg;
6902                 }
6903         }
6904         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6905 }
6906
6907 static const char *
6908 subevalvar(char *p, char *varname, int strloc, int subtype,
6909                 int startloc, int varflags, int flag)
6910 {
6911         struct nodelist *saveargbackq = argbackq;
6912         int quotes = flag & QUOTES_ESC;
6913         char *startp;
6914         char *loc;
6915         char *rmesc, *rmescend;
6916         char *str;
6917         int amount, resetloc;
6918         int argstr_flags;
6919         IF_BASH_PATTERN_SUBST(int workloc;)
6920         IF_BASH_PATTERN_SUBST(int slash_pos;)
6921         IF_BASH_PATTERN_SUBST(char *repl;)
6922         int zero;
6923         char *(*scan)(char*, char*, char*, char*, int, int);
6924
6925         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6926         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6927
6928 #if BASH_PATTERN_SUBST
6929         /* For "${v/pattern/repl}", we must find the delimiter _before_
6930          * argstr() call expands possible variable references in pattern:
6931          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6932          */
6933         repl = NULL;
6934         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6935                 /* Find '/' and replace with NUL */
6936                 repl = p;
6937                 /* The pattern can't be empty.
6938                  * IOW: if the first char after "${v//" is a slash,
6939                  * it does not terminate the pattern - it's the first char of the pattern:
6940                  *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
6941                  *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
6942                  */
6943                 if (*repl == '/')
6944                         repl++;
6945                 for (;;) {
6946                         if (*repl == '\0') {
6947                                 repl = NULL;
6948                                 break;
6949                         }
6950                         if (*repl == '/') {
6951                                 *repl = '\0';
6952                                 break;
6953                         }
6954                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6955                         if ((unsigned char)*repl == CTLESC && repl[1])
6956                                 repl++;
6957                         repl++;
6958                 }
6959         }
6960 #endif
6961         argstr_flags = EXP_TILDE;
6962         if (subtype != VSASSIGN
6963          && subtype != VSQUESTION
6964 #if BASH_SUBSTR
6965          && subtype != VSSUBSTR
6966 #endif
6967         ) {
6968                 /* EXP_CASE keeps CTLESC's */
6969                 argstr_flags = EXP_TILDE | EXP_CASE;
6970         }
6971         argstr(p, argstr_flags);
6972         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6973 #if BASH_PATTERN_SUBST
6974         slash_pos = -1;
6975         if (repl) {
6976                 slash_pos = expdest - ((char *)stackblock() + strloc);
6977                 STPUTC('/', expdest);
6978                 //bb_error_msg("repl+1:'%s'", repl + 1);
6979                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6980                 *repl = '/';
6981         }
6982 #endif
6983         STPUTC('\0', expdest);
6984         argbackq = saveargbackq;
6985         startp = (char *)stackblock() + startloc;
6986         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6987
6988         switch (subtype) {
6989         case VSASSIGN:
6990                 setvar0(varname, startp);
6991                 amount = startp - expdest;
6992                 STADJUST(amount, expdest);
6993                 return startp;
6994
6995         case VSQUESTION:
6996                 varunset(p, varname, startp, varflags);
6997                 /* NOTREACHED */
6998
6999 #if BASH_SUBSTR
7000         case VSSUBSTR: {
7001                 int pos, len, orig_len;
7002                 char *colon;
7003
7004                 loc = str = stackblock() + strloc;
7005
7006                 /* Read POS in ${var:POS:LEN} */
7007                 colon = strchr(loc, ':');
7008                 if (colon) *colon = '\0';
7009                 pos = substr_atoi(loc);
7010                 if (colon) *colon = ':';
7011
7012                 /* Read LEN in ${var:POS:LEN} */
7013                 len = str - startp - 1;
7014                 /* *loc != '\0', guaranteed by parser */
7015                 if (quotes) {
7016                         char *ptr;
7017                         /* Adjust the length by the number of escapes */
7018                         for (ptr = startp; ptr < (str - 1); ptr++) {
7019                                 if ((unsigned char)*ptr == CTLESC) {
7020                                         len--;
7021                                         ptr++;
7022                                 }
7023                         }
7024                 }
7025                 orig_len = len;
7026                 if (*loc++ == ':') {
7027                         /* ${var::LEN} */
7028                         len = substr_atoi(loc);
7029                 } else {
7030                         /* Skip POS in ${var:POS:LEN} */
7031                         len = orig_len;
7032                         while (*loc && *loc != ':')
7033                                 loc++;
7034                         if (*loc++ == ':')
7035                                 len = substr_atoi(loc);
7036                 }
7037                 if (pos < 0) {
7038                         /* ${VAR:$((-n)):l} starts n chars from the end */
7039                         pos = orig_len + pos;
7040                 }
7041                 if ((unsigned)pos >= orig_len) {
7042                         /* apart from obvious ${VAR:999999:l},
7043                          * covers ${VAR:$((-9999999)):l} - result is ""
7044                          * (bash compat)
7045                          */
7046                         pos = 0;
7047                         len = 0;
7048                 }
7049                 if (len < 0) {
7050                         /* ${VAR:N:-M} sets LEN to strlen()-M */
7051                         len = (orig_len - pos) + len;
7052                 }
7053                 if ((unsigned)len > (orig_len - pos))
7054                         len = orig_len - pos;
7055
7056                 for (str = startp; pos; str++, pos--) {
7057                         if (quotes && (unsigned char)*str == CTLESC)
7058                                 str++;
7059                 }
7060                 for (loc = startp; len; len--) {
7061                         if (quotes && (unsigned char)*str == CTLESC)
7062                                 *loc++ = *str++;
7063                         *loc++ = *str++;
7064                 }
7065                 *loc = '\0';
7066                 amount = loc - expdest;
7067                 STADJUST(amount, expdest);
7068                 return loc;
7069         }
7070 #endif /* BASH_SUBSTR */
7071         }
7072
7073         resetloc = expdest - (char *)stackblock();
7074
7075 #if BASH_PATTERN_SUBST
7076         repl = NULL;
7077
7078         /* We'll comeback here if we grow the stack while handling
7079          * a VSREPLACE or VSREPLACEALL, since our pointers into the
7080          * stack will need rebasing, and we'll need to remove our work
7081          * areas each time
7082          */
7083  restart:
7084 #endif
7085
7086         amount = expdest - ((char *)stackblock() + resetloc);
7087         STADJUST(-amount, expdest);
7088         startp = (char *)stackblock() + startloc;
7089
7090         rmesc = startp;
7091         rmescend = (char *)stackblock() + strloc;
7092         //bb_error_msg("str7:'%s'", rmescend);
7093         if (quotes) {
7094 //TODO: how to handle slash_pos here if string changes (shortens?)
7095                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7096                 if (rmesc != startp) {
7097                         rmescend = expdest;
7098                         startp = (char *)stackblock() + startloc;
7099                 }
7100         }
7101         rmescend--;
7102         str = (char *)stackblock() + strloc;
7103         /*
7104          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7105          * The result is a_\_z_c (not a\_\_z_c)!
7106          *
7107          * The search pattern and replace string treat backslashes differently!
7108          * "&slash_pos" causes rmescapes() to work differently on the pattern
7109          * and string.  It's only used on the first call.
7110          */
7111         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7112         rmescapes(str, RMESCAPE_GLOB,
7113                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7114         );
7115
7116 #if BASH_PATTERN_SUBST
7117         workloc = expdest - (char *)stackblock();
7118         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7119                 int len;
7120                 char *idx, *end;
7121
7122                 if (!repl) {
7123                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7124                         repl = nullstr;
7125                         if (slash_pos >= 0) {
7126                                 repl = str + slash_pos;
7127                                 *repl++ = '\0';
7128                         }
7129                 }
7130                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7131
7132                 /* If there's no pattern to match, return the expansion unmolested */
7133                 if (str[0] == '\0')
7134                         return NULL;
7135
7136                 len = 0;
7137                 idx = startp;
7138                 end = str - 1;
7139                 while (idx < end) {
7140  try_to_match:
7141                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7142                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7143                         if (!loc) {
7144                                 /* No match, advance */
7145                                 char *restart_detect = stackblock();
7146  skip_matching:
7147                                 STPUTC(*idx, expdest);
7148                                 if (quotes && (unsigned char)*idx == CTLESC) {
7149                                         idx++;
7150                                         len++;
7151                                         STPUTC(*idx, expdest);
7152                                 }
7153                                 if (stackblock() != restart_detect)
7154                                         goto restart;
7155                                 idx++;
7156                                 len++;
7157                                 rmesc++;
7158                                 /* continue; - prone to quadratic behavior, smarter code: */
7159                                 if (idx >= end)
7160                                         break;
7161                                 if (str[0] == '*') {
7162                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7163                                          * it would never match "ong_string" etc, no point in trying.
7164                                          */
7165                                         goto skip_matching;
7166                                 }
7167                                 goto try_to_match;
7168                         }
7169
7170                         if (subtype == VSREPLACEALL) {
7171                                 while (idx < loc) {
7172                                         if (quotes && (unsigned char)*idx == CTLESC)
7173                                                 idx++;
7174                                         idx++;
7175                                         rmesc++;
7176                                 }
7177                         } else {
7178                                 idx = loc;
7179                         }
7180
7181                         //bb_error_msg("repl:'%s'", repl);
7182                         for (loc = (char*)repl; *loc; loc++) {
7183                                 char *restart_detect = stackblock();
7184                                 if (quotes && *loc == '\\') {
7185                                         STPUTC(CTLESC, expdest);
7186                                         len++;
7187                                 }
7188                                 STPUTC(*loc, expdest);
7189                                 if (stackblock() != restart_detect)
7190                                         goto restart;
7191                                 len++;
7192                         }
7193
7194                         if (subtype == VSREPLACE) {
7195                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7196                                 while (*idx) {
7197                                         char *restart_detect = stackblock();
7198                                         STPUTC(*idx, expdest);
7199                                         if (stackblock() != restart_detect)
7200                                                 goto restart;
7201                                         len++;
7202                                         idx++;
7203                                 }
7204                                 break;
7205                         }
7206                 }
7207
7208                 /* We've put the replaced text into a buffer at workloc, now
7209                  * move it to the right place and adjust the stack.
7210                  */
7211                 STPUTC('\0', expdest);
7212                 startp = (char *)stackblock() + startloc;
7213                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7214                 //bb_error_msg("startp:'%s'", startp);
7215                 amount = expdest - (startp + len);
7216                 STADJUST(-amount, expdest);
7217                 return startp;
7218         }
7219 #endif /* BASH_PATTERN_SUBST */
7220
7221         subtype -= VSTRIMRIGHT;
7222 #if DEBUG
7223         if (subtype < 0 || subtype > 7)
7224                 abort();
7225 #endif
7226         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7227         zero = subtype >> 1;
7228         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7229         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7230
7231         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7232         if (loc) {
7233                 if (zero) {
7234                         memmove(startp, loc, str - loc);
7235                         loc = startp + (str - loc) - 1;
7236                 }
7237                 *loc = '\0';
7238                 amount = loc - expdest;
7239                 STADJUST(amount, expdest);
7240         }
7241         return loc;
7242 }
7243
7244 /*
7245  * Add the value of a specialized variable to the stack string.
7246  * name parameter (examples):
7247  * ash -c 'echo $1'      name:'1='
7248  * ash -c 'echo $qwe'    name:'qwe='
7249  * ash -c 'echo $$'      name:'$='
7250  * ash -c 'echo ${$}'    name:'$='
7251  * ash -c 'echo ${$##q}' name:'$=q'
7252  * ash -c 'echo ${#$}'   name:'$='
7253  * note: examples with bad shell syntax:
7254  * ash -c 'echo ${#$1}'  name:'$=1'
7255  * ash -c 'echo ${#1#}'  name:'1=#'
7256  */
7257 static NOINLINE ssize_t
7258 varvalue(char *name, int varflags, int flags, int quoted)
7259 {
7260         const char *p;
7261         int num;
7262         int i;
7263         ssize_t len = 0;
7264         int sep;
7265         int subtype = varflags & VSTYPE;
7266         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7267         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7268         int syntax;
7269
7270         sep = (flags & EXP_FULL) << CHAR_BIT;
7271         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7272
7273         switch (*name) {
7274         case '$':
7275                 num = rootpid;
7276                 goto numvar;
7277         case '?':
7278                 num = exitstatus;
7279                 goto numvar;
7280         case '#':
7281                 num = shellparam.nparam;
7282                 goto numvar;
7283         case '!':
7284                 num = backgndpid;
7285                 if (num == 0)
7286                         return -1;
7287  numvar:
7288                 len = cvtnum(num);
7289                 goto check_1char_name;
7290         case '-':
7291                 expdest = makestrspace(NOPTS, expdest);
7292                 for (i = NOPTS - 1; i >= 0; i--) {
7293                         if (optlist[i] && optletters(i)) {
7294                                 USTPUTC(optletters(i), expdest);
7295                                 len++;
7296                         }
7297                 }
7298  check_1char_name:
7299 #if 0
7300                 /* handles cases similar to ${#$1} */
7301                 if (name[2] != '\0')
7302                         raise_error_syntax("bad substitution");
7303 #endif
7304                 break;
7305         case '@':
7306                 if (quoted && sep)
7307                         goto param;
7308                 /* fall through */
7309         case '*': {
7310                 char **ap;
7311                 char sepc;
7312                 char c;
7313
7314                 /* We will set c to 0 or ~0 depending on whether
7315                  * we're doing field splitting.  We won't do field
7316                  * splitting if either we're quoted or sep is zero.
7317                  *
7318                  * Instead of testing (quoted || !sep) the following
7319                  * trick optimises away any branches by using the
7320                  * fact that EXP_QUOTED (which is the only bit that
7321                  * can be set in quoted) is the same as EXP_FULL <<
7322                  * CHAR_BIT (which is the only bit that can be set
7323                  * in sep).
7324                  */
7325 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7326 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7327 #endif
7328                 c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7329                 sep &= ~quoted;
7330                 sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7331  param:
7332                 sepc = sep;
7333                 ap = shellparam.p;
7334                 if (!ap)
7335                         return -1;
7336                 while ((p = *ap++) != NULL) {
7337                         len += strtodest(p, syntax, quotes);
7338
7339                         if (*ap && sep) {
7340                                 len++;
7341                                 memtodest(&sepc, 1, syntax, quotes);
7342                         }
7343                 }
7344                 break;
7345         } /* case '*' */
7346         case '0':
7347         case '1':
7348         case '2':
7349         case '3':
7350         case '4':
7351         case '5':
7352         case '6':
7353         case '7':
7354         case '8':
7355         case '9':
7356                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7357                 if (num < 0 || num > shellparam.nparam)
7358                         return -1;
7359                 p = num ? shellparam.p[num - 1] : arg0;
7360                 goto value;
7361         default:
7362                 /* NB: name has form "VAR=..." */
7363                 p = lookupvar(name);
7364  value:
7365                 if (!p)
7366                         return -1;
7367
7368                 len = strtodest(p, syntax, quotes);
7369 #if ENABLE_UNICODE_SUPPORT
7370                 if (subtype == VSLENGTH && len > 0) {
7371                         reinit_unicode_for_ash();
7372                         if (unicode_status == UNICODE_ON) {
7373                                 STADJUST(-len, expdest);
7374                                 discard = 0;
7375                                 len = unicode_strlen(p);
7376                         }
7377                 }
7378 #endif
7379                 break;
7380         }
7381
7382         if (discard)
7383                 STADJUST(-len, expdest);
7384         return len;
7385 }
7386
7387 /*
7388  * Expand a variable, and return a pointer to the next character in the
7389  * input string.
7390  */
7391 static char *
7392 evalvar(char *p, int flag)
7393 {
7394         char varflags;
7395         char subtype;
7396         int quoted;
7397         char *var;
7398         int patloc;
7399         int startloc;
7400         ssize_t varlen;
7401
7402         varflags = (unsigned char) *p++;
7403         subtype = varflags & VSTYPE;
7404
7405         if (!subtype)
7406                 raise_error_syntax("bad substitution");
7407
7408         quoted = flag & EXP_QUOTED;
7409         var = p;
7410         startloc = expdest - (char *)stackblock();
7411         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7412
7413  again:
7414         varlen = varvalue(var, varflags, flag, quoted);
7415         if (varflags & VSNUL)
7416                 varlen--;
7417
7418         if (subtype == VSPLUS) {
7419                 varlen = -1 - varlen;
7420                 goto vsplus;
7421         }
7422
7423         if (subtype == VSMINUS) {
7424  vsplus:
7425                 if (varlen < 0) {
7426                         argstr(
7427                                 p,
7428                                 flag | EXP_TILDE | EXP_WORD
7429                         );
7430                         goto end;
7431                 }
7432                 goto record;
7433         }
7434
7435         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7436                 if (varlen >= 0)
7437                         goto record;
7438
7439                 subevalvar(p, var, 0, subtype, startloc, varflags,
7440                            flag & ~QUOTES_ESC);
7441                 varflags &= ~VSNUL;
7442                 /*
7443                  * Remove any recorded regions beyond
7444                  * start of variable
7445                  */
7446                 removerecordregions(startloc);
7447                 goto again;
7448         }
7449
7450         if (varlen < 0 && uflag)
7451                 varunset(p, var, 0, 0);
7452
7453         if (subtype == VSLENGTH) {
7454                 cvtnum(varlen > 0 ? varlen : 0);
7455                 goto record;
7456         }
7457
7458         if (subtype == VSNORMAL) {
7459  record:
7460                 if (quoted) {
7461                         quoted = *var == '@' && shellparam.nparam;
7462                         if (!quoted)
7463                                 goto end;
7464                 }
7465                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7466                 goto end;
7467         }
7468
7469 #if DEBUG
7470         switch (subtype) {
7471         case VSTRIMLEFT:
7472         case VSTRIMLEFTMAX:
7473         case VSTRIMRIGHT:
7474         case VSTRIMRIGHTMAX:
7475 #if BASH_SUBSTR
7476         case VSSUBSTR:
7477 #endif
7478 #if BASH_PATTERN_SUBST
7479         case VSREPLACE:
7480         case VSREPLACEALL:
7481 #endif
7482                 break;
7483         default:
7484                 abort();
7485         }
7486 #endif
7487
7488         if (varlen >= 0) {
7489                 /*
7490                  * Terminate the string and start recording the pattern
7491                  * right after it
7492                  */
7493                 STPUTC('\0', expdest);
7494                 patloc = expdest - (char *)stackblock();
7495                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7496                                 startloc, varflags, flag)) {
7497                         int amount = expdest - (
7498                                 (char *)stackblock() + patloc - 1
7499                         );
7500                         STADJUST(-amount, expdest);
7501                 }
7502                 /* Remove any recorded regions beyond start of variable */
7503                 removerecordregions(startloc);
7504                 goto record;
7505         }
7506
7507  end:
7508         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7509                 int nesting = 1;
7510                 for (;;) {
7511                         unsigned char c = *p++;
7512                         if (c == CTLESC)
7513                                 p++;
7514                         else if (c == CTLBACKQ) {
7515                                 if (varlen >= 0)
7516                                         argbackq = argbackq->next;
7517                         } else if (c == CTLVAR) {
7518                                 if ((*p++ & VSTYPE) != VSNORMAL)
7519                                         nesting++;
7520                         } else if (c == CTLENDVAR) {
7521                                 if (--nesting == 0)
7522                                         break;
7523                         }
7524                 }
7525         }
7526         return p;
7527 }
7528
7529 /*
7530  * Add a file name to the list.
7531  */
7532 static void
7533 addfname(const char *name)
7534 {
7535         struct strlist *sp;
7536
7537         sp = stzalloc(sizeof(*sp));
7538         sp->text = sstrdup(name);
7539         *exparg.lastp = sp;
7540         exparg.lastp = &sp->next;
7541 }
7542
7543 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7544 static int
7545 hasmeta(const char *p)
7546 {
7547         static const char chars[] ALIGN1 = {
7548                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7549         };
7550
7551         for (;;) {
7552                 p = strpbrk(p, chars);
7553                 if (!p)
7554                         break;
7555                 switch ((unsigned char)*p) {
7556                 case CTLQUOTEMARK:
7557                         for (;;) {
7558                                 p++;
7559                                 if ((unsigned char)*p == CTLQUOTEMARK)
7560                                         break;
7561                                 if ((unsigned char)*p == CTLESC)
7562                                         p++;
7563                                 if (*p == '\0') /* huh? */
7564                                         return 0;
7565                         }
7566                         break;
7567                 case '\\':
7568                 case CTLESC:
7569                         p++;
7570                         if (*p == '\0')
7571                                 return 0;
7572                         break;
7573                 case '[':
7574                         if (!strchr(p + 1, ']')) {
7575                                 /* It's not a properly closed [] pattern,
7576                                  * but other metas may follow. Continue checking.
7577                                  * my[file* _is_ globbed by bash
7578                                  * and matches filenames like "my[file1".
7579                                  */
7580                                 break;
7581                         }
7582                         /* fallthrough */
7583                 default:
7584                 /* case '*': */
7585                 /* case '?': */
7586                         return 1;
7587                 }
7588                 p++;
7589         }
7590
7591         return 0;
7592 }
7593
7594 /* If we want to use glob() from libc... */
7595 #if !ENABLE_ASH_INTERNAL_GLOB
7596
7597 /* Add the result of glob() to the list */
7598 static void
7599 addglob(const glob_t *pglob)
7600 {
7601         char **p = pglob->gl_pathv;
7602
7603         do {
7604                 addfname(*p);
7605         } while (*++p);
7606 }
7607 static void
7608 expandmeta(struct strlist *str /*, int flag*/)
7609 {
7610         /* TODO - EXP_REDIR */
7611
7612         while (str) {
7613                 char *p;
7614                 glob_t pglob;
7615                 int i;
7616
7617                 if (fflag)
7618                         goto nometa;
7619
7620                 if (!hasmeta(str->text))
7621                         goto nometa;
7622
7623                 INT_OFF;
7624                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7625 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7626 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7627 //
7628 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7629 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7630 // Which means you need to unescape the string, right? Not so fast:
7631 // if there _is_ a file named "file\?" (with backslash), it is returned
7632 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7633 // You DON'T KNOW by looking at the result whether you need to unescape it.
7634 //
7635 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7636 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7637 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7638 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7639 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7640 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7641                 i = glob(p, 0, NULL, &pglob);
7642                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7643                 if (p != str->text)
7644                         free(p);
7645                 switch (i) {
7646                 case 0:
7647 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7648                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7649                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7650                                 goto nometa2;
7651 #endif
7652                         addglob(&pglob);
7653                         globfree(&pglob);
7654                         INT_ON;
7655                         break;
7656                 case GLOB_NOMATCH:
7657  //nometa2:
7658                         globfree(&pglob);
7659                         INT_ON;
7660  nometa:
7661                         *exparg.lastp = str;
7662                         rmescapes(str->text, 0, NULL);
7663                         exparg.lastp = &str->next;
7664                         break;
7665                 default:        /* GLOB_NOSPACE */
7666                         globfree(&pglob);
7667                         INT_ON;
7668                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7669                 }
7670                 str = str->next;
7671         }
7672 }
7673
7674 #else
7675 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7676
7677 /*
7678  * Do metacharacter (i.e. *, ?, [...]) expansion.
7679  */
7680 typedef struct exp_t {
7681         char *dir;
7682         unsigned dir_max;
7683 } exp_t;
7684 static void
7685 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7686 {
7687 #define expdir exp->dir
7688 #define expdir_max exp->dir_max
7689         char *enddir = expdir + expdir_len;
7690         char *p;
7691         const char *cp;
7692         char *start;
7693         char *endname;
7694         int metaflag;
7695         struct stat statb;
7696         DIR *dirp;
7697         struct dirent *dp;
7698         int atend;
7699         int matchdot;
7700         int esc;
7701
7702         metaflag = 0;
7703         start = name;
7704         for (p = name; esc = 0, *p; p += esc + 1) {
7705                 if (*p == '*' || *p == '?')
7706                         metaflag = 1;
7707                 else if (*p == '[') {
7708                         char *q = p + 1;
7709                         if (*q == '!')
7710                                 q++;
7711                         for (;;) {
7712                                 if (*q == '\\')
7713                                         q++;
7714                                 if (*q == '/' || *q == '\0')
7715                                         break;
7716                                 if (*++q == ']') {
7717                                         metaflag = 1;
7718                                         break;
7719                                 }
7720                         }
7721                 } else {
7722                         if (*p == '\\' && p[1])
7723                                 esc++;
7724                         if (p[esc] == '/') {
7725                                 if (metaflag)
7726                                         break;
7727                                 start = p + esc + 1;
7728                         }
7729                 }
7730         }
7731         if (metaflag == 0) {    /* we've reached the end of the file name */
7732                 if (!expdir_len)
7733                         return;
7734                 p = name;
7735                 do {
7736                         if (*p == '\\' && p[1])
7737                                 p++;
7738                         *enddir++ = *p;
7739                 } while (*p++);
7740                 if (lstat(expdir, &statb) == 0)
7741                         addfname(expdir);
7742                 return;
7743         }
7744         endname = p;
7745         if (name < start) {
7746                 p = name;
7747                 do {
7748                         if (*p == '\\' && p[1])
7749                                 p++;
7750                         *enddir++ = *p++;
7751                 } while (p < start);
7752         }
7753         *enddir = '\0';
7754         cp = expdir;
7755         expdir_len = enddir - cp;
7756         if (!expdir_len)
7757                 cp = ".";
7758         dirp = opendir(cp);
7759         if (dirp == NULL)
7760                 return;
7761         if (*endname == 0) {
7762                 atend = 1;
7763         } else {
7764                 atend = 0;
7765                 *endname = '\0';
7766                 endname += esc + 1;
7767         }
7768         name_len -= endname - name;
7769         matchdot = 0;
7770         p = start;
7771         if (*p == '\\')
7772                 p++;
7773         if (*p == '.')
7774                 matchdot++;
7775         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7776                 if (dp->d_name[0] == '.' && !matchdot)
7777                         continue;
7778                 if (pmatch(start, dp->d_name)) {
7779                         if (atend) {
7780                                 strcpy(enddir, dp->d_name);
7781                                 addfname(expdir);
7782                         } else {
7783                                 unsigned offset;
7784                                 unsigned len;
7785
7786                                 p = stpcpy(enddir, dp->d_name);
7787                                 *p = '/';
7788
7789                                 offset = p - expdir + 1;
7790                                 len = offset + name_len + NAME_MAX;
7791                                 if (len > expdir_max) {
7792                                         len += PATH_MAX;
7793                                         expdir = ckrealloc(expdir, len);
7794                                         expdir_max = len;
7795                                 }
7796
7797                                 expmeta(exp, endname, name_len, offset);
7798                                 enddir = expdir + expdir_len;
7799                         }
7800                 }
7801         }
7802         closedir(dirp);
7803         if (!atend)
7804                 endname[-esc - 1] = esc ? '\\' : '/';
7805 #undef expdir
7806 #undef expdir_max
7807 }
7808
7809 static struct strlist *
7810 msort(struct strlist *list, int len)
7811 {
7812         struct strlist *p, *q = NULL;
7813         struct strlist **lpp;
7814         int half;
7815         int n;
7816
7817         if (len <= 1)
7818                 return list;
7819         half = len >> 1;
7820         p = list;
7821         for (n = half; --n >= 0;) {
7822                 q = p;
7823                 p = p->next;
7824         }
7825         q->next = NULL;                 /* terminate first half of list */
7826         q = msort(list, half);          /* sort first half of list */
7827         p = msort(p, len - half);               /* sort second half */
7828         lpp = &list;
7829         for (;;) {
7830 #if ENABLE_LOCALE_SUPPORT
7831                 if (strcoll(p->text, q->text) < 0)
7832 #else
7833                 if (strcmp(p->text, q->text) < 0)
7834 #endif
7835                                                 {
7836                         *lpp = p;
7837                         lpp = &p->next;
7838                         p = *lpp;
7839                         if (p == NULL) {
7840                                 *lpp = q;
7841                                 break;
7842                         }
7843                 } else {
7844                         *lpp = q;
7845                         lpp = &q->next;
7846                         q = *lpp;
7847                         if (q == NULL) {
7848                                 *lpp = p;
7849                                 break;
7850                         }
7851                 }
7852         }
7853         return list;
7854 }
7855
7856 /*
7857  * Sort the results of file name expansion.  It calculates the number of
7858  * strings to sort and then calls msort (short for merge sort) to do the
7859  * work.
7860  */
7861 static struct strlist *
7862 expsort(struct strlist *str)
7863 {
7864         int len;
7865         struct strlist *sp;
7866
7867         len = 0;
7868         for (sp = str; sp; sp = sp->next)
7869                 len++;
7870         return msort(str, len);
7871 }
7872
7873 static void
7874 expandmeta(struct strlist *str /*, int flag*/)
7875 {
7876         /* TODO - EXP_REDIR */
7877
7878         while (str) {
7879                 exp_t exp;
7880                 struct strlist **savelastp;
7881                 struct strlist *sp;
7882                 char *p;
7883                 unsigned len;
7884
7885                 if (fflag)
7886                         goto nometa;
7887                 if (!hasmeta(str->text))
7888                         goto nometa;
7889                 savelastp = exparg.lastp;
7890
7891                 INT_OFF;
7892                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7893                 len = strlen(p);
7894                 exp.dir_max = len + PATH_MAX;
7895                 exp.dir = ckmalloc(exp.dir_max);
7896
7897                 expmeta(&exp, p, len, 0);
7898                 free(exp.dir);
7899                 if (p != str->text)
7900                         free(p);
7901                 INT_ON;
7902                 if (exparg.lastp == savelastp) {
7903                         /*
7904                          * no matches
7905                          */
7906  nometa:
7907                         *exparg.lastp = str;
7908                         rmescapes(str->text, 0, NULL);
7909                         exparg.lastp = &str->next;
7910                 } else {
7911                         *exparg.lastp = NULL;
7912                         *savelastp = sp = expsort(*savelastp);
7913                         while (sp->next != NULL)
7914                                 sp = sp->next;
7915                         exparg.lastp = &sp->next;
7916                 }
7917                 str = str->next;
7918         }
7919 }
7920 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7921
7922 /*
7923  * Perform variable substitution and command substitution on an argument,
7924  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7925  * perform splitting and file name expansion.  When arglist is NULL, perform
7926  * here document expansion.
7927  */
7928 static void
7929 expandarg(union node *arg, struct arglist *arglist, int flag)
7930 {
7931         struct strlist *sp;
7932         char *p;
7933
7934         argbackq = arg->narg.backquote;
7935         STARTSTACKSTR(expdest);
7936         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7937         argstr(arg->narg.text, flag);
7938         p = _STPUTC('\0', expdest);
7939         expdest = p - 1;
7940         if (arglist == NULL) {
7941                 /* here document expanded */
7942                 goto out;
7943         }
7944         p = grabstackstr(p);
7945         TRACE(("expandarg: p:'%s'\n", p));
7946         exparg.lastp = &exparg.list;
7947         /*
7948          * TODO - EXP_REDIR
7949          */
7950         if (flag & EXP_FULL) {
7951                 ifsbreakup(p, &exparg);
7952                 *exparg.lastp = NULL;
7953                 exparg.lastp = &exparg.list;
7954                 expandmeta(exparg.list /*, flag*/);
7955         } else {
7956                 sp = stzalloc(sizeof(*sp));
7957                 sp->text = p;
7958                 *exparg.lastp = sp;
7959                 exparg.lastp = &sp->next;
7960         }
7961         *exparg.lastp = NULL;
7962         if (exparg.list) {
7963                 *arglist->lastp = exparg.list;
7964                 arglist->lastp = exparg.lastp;
7965         }
7966
7967  out:
7968         ifsfree();
7969 }
7970
7971 /*
7972  * Expand shell variables and backquotes inside a here document.
7973  */
7974 static void
7975 expandhere(union node *arg, int fd)
7976 {
7977         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7978         full_write(fd, stackblock(), expdest - (char *)stackblock());
7979 }
7980
7981 /*
7982  * Returns true if the pattern matches the string.
7983  */
7984 static int
7985 patmatch(char *pattern, const char *string)
7986 {
7987         char *p = preglob(pattern, 0);
7988         int r = pmatch(p, string);
7989         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7990         return r;
7991 }
7992
7993 /*
7994  * See if a pattern matches in a case statement.
7995  */
7996 static int
7997 casematch(union node *pattern, char *val)
7998 {
7999         struct stackmark smark;
8000         int result;
8001
8002         setstackmark(&smark);
8003         argbackq = pattern->narg.backquote;
8004         STARTSTACKSTR(expdest);
8005         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8006         STACKSTRNUL(expdest);
8007         ifsfree();
8008         result = patmatch(stackblock(), val);
8009         popstackmark(&smark);
8010         return result;
8011 }
8012
8013
8014 /* ============ find_command */
8015
8016 struct builtincmd {
8017         const char *name;
8018         int (*builtin)(int, char **) FAST_FUNC;
8019         /* unsigned flags; */
8020 };
8021 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8022 /* "regular" builtins always take precedence over commands,
8023  * regardless of PATH=....%builtin... position */
8024 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8025 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
8026
8027 struct cmdentry {
8028         smallint cmdtype;       /* CMDxxx */
8029         union param {
8030                 int index;
8031                 /* index >= 0 for commands without path (slashes) */
8032                 /* (TODO: what exactly does the value mean? PATH position?) */
8033                 /* index == -1 for commands with slashes */
8034                 /* index == (-2 - applet_no) for NOFORK applets */
8035                 const struct builtincmd *cmd;
8036                 struct funcnode *func;
8037         } u;
8038 };
8039 /* values of cmdtype */
8040 #define CMDUNKNOWN      -1      /* no entry in table for command */
8041 #define CMDNORMAL       0       /* command is an executable program */
8042 #define CMDFUNCTION     1       /* command is a shell function */
8043 #define CMDBUILTIN      2       /* command is a shell builtin */
8044
8045 /* action to find_command() */
8046 #define DO_ERR          0x01    /* prints errors */
8047 #define DO_ABS          0x02    /* checks absolute paths */
8048 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
8049 #define DO_ALTPATH      0x08    /* using alternate path */
8050 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
8051
8052 static void find_command(char *, struct cmdentry *, int, const char *);
8053
8054
8055 /* ============ Hashing commands */
8056
8057 /*
8058  * When commands are first encountered, they are entered in a hash table.
8059  * This ensures that a full path search will not have to be done for them
8060  * on each invocation.
8061  *
8062  * We should investigate converting to a linear search, even though that
8063  * would make the command name "hash" a misnomer.
8064  */
8065
8066 struct tblentry {
8067         struct tblentry *next;  /* next entry in hash chain */
8068         union param param;      /* definition of builtin function */
8069         smallint cmdtype;       /* CMDxxx */
8070         char rehash;            /* if set, cd done since entry created */
8071         char cmdname[1];        /* name of command */
8072 };
8073
8074 static struct tblentry **cmdtable;
8075 #define INIT_G_cmdtable() do { \
8076         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8077 } while (0)
8078
8079 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8080
8081
8082 static void
8083 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8084 {
8085 #if ENABLE_FEATURE_SH_STANDALONE
8086         if (applet_no >= 0) {
8087                 if (APPLET_IS_NOEXEC(applet_no)) {
8088                         clearenv();
8089                         while (*envp)
8090                                 putenv(*envp++);
8091                         popredir(/*drop:*/ 1);
8092                         run_noexec_applet_and_exit(applet_no, cmd, argv);
8093                 }
8094                 /* re-exec ourselves with the new arguments */
8095                 execve(bb_busybox_exec_path, argv, envp);
8096                 /* If they called chroot or otherwise made the binary no longer
8097                  * executable, fall through */
8098         }
8099 #endif
8100
8101  repeat:
8102 #ifdef SYSV
8103         do {
8104                 execve(cmd, argv, envp);
8105         } while (errno == EINTR);
8106 #else
8107         execve(cmd, argv, envp);
8108 #endif
8109
8110         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8111                 /* Run "cmd" as a shell script:
8112                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8113                  * "If the execve() function fails with ENOEXEC, the shell
8114                  * shall execute a command equivalent to having a shell invoked
8115                  * with the command name as its first operand,
8116                  * with any remaining arguments passed to the new shell"
8117                  *
8118                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8119                  * just call ourselves.
8120                  *
8121                  * Note that bash reads ~80 chars of the file, and if it sees
8122                  * a zero byte before it sees newline, it doesn't try to
8123                  * interpret it, but fails with "cannot execute binary file"
8124                  * message and exit code 126. For one, this prevents attempts
8125                  * to interpret foreign ELF binaries as shell scripts.
8126                  */
8127                 argv[0] = (char*) cmd;
8128                 cmd = bb_busybox_exec_path;
8129                 /* NB: this is only possible because all callers of shellexec()
8130                  * ensure that the argv[-1] slot exists!
8131                  */
8132                 argv--;
8133                 argv[0] = (char*) "ash";
8134                 goto repeat;
8135         }
8136 }
8137
8138 /*
8139  * Exec a program.  Never returns.  If you change this routine, you may
8140  * have to change the find_command routine as well.
8141  * argv[-1] must exist and be writable! See tryexec() for why.
8142  */
8143 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8144 static void shellexec(char *prog, char **argv, const char *path, int idx)
8145 {
8146         char *cmdname;
8147         int e;
8148         char **envp;
8149         int exerrno;
8150         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8151
8152         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8153         if (strchr(prog, '/') != NULL
8154 #if ENABLE_FEATURE_SH_STANDALONE
8155          || (applet_no = find_applet_by_name(prog)) >= 0
8156 #endif
8157         ) {
8158                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8159                 if (applet_no >= 0) {
8160                         /* We tried execing ourself, but it didn't work.
8161                          * Maybe /proc/self/exe doesn't exist?
8162                          * Try $PATH search.
8163                          */
8164                         goto try_PATH;
8165                 }
8166                 e = errno;
8167         } else {
8168  try_PATH:
8169                 e = ENOENT;
8170                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8171                         if (--idx < 0 && pathopt == NULL) {
8172                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8173                                 if (errno != ENOENT && errno != ENOTDIR)
8174                                         e = errno;
8175                         }
8176                         stunalloc(cmdname);
8177                 }
8178         }
8179
8180         /* Map to POSIX errors */
8181         switch (e) {
8182         default:
8183                 exerrno = 126;
8184                 break;
8185         case ELOOP:
8186         case ENAMETOOLONG:
8187         case ENOENT:
8188         case ENOTDIR:
8189                 exerrno = 127;
8190                 break;
8191         }
8192         exitstatus = exerrno;
8193         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8194                 prog, e, suppress_int));
8195         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8196         /* NOTREACHED */
8197 }
8198
8199 static void
8200 printentry(struct tblentry *cmdp)
8201 {
8202         int idx;
8203         const char *path;
8204         char *name;
8205
8206         idx = cmdp->param.index;
8207         path = pathval();
8208         do {
8209                 name = path_advance(&path, cmdp->cmdname);
8210                 stunalloc(name);
8211         } while (--idx >= 0);
8212         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8213 }
8214
8215 /*
8216  * Clear out command entries.  The argument specifies the first entry in
8217  * PATH which has changed.
8218  */
8219 static void
8220 clearcmdentry(int firstchange)
8221 {
8222         struct tblentry **tblp;
8223         struct tblentry **pp;
8224         struct tblentry *cmdp;
8225
8226         INT_OFF;
8227         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8228                 pp = tblp;
8229                 while ((cmdp = *pp) != NULL) {
8230                         if ((cmdp->cmdtype == CMDNORMAL &&
8231                              cmdp->param.index >= firstchange)
8232                          || (cmdp->cmdtype == CMDBUILTIN &&
8233                              builtinloc >= firstchange)
8234                         ) {
8235                                 *pp = cmdp->next;
8236                                 free(cmdp);
8237                         } else {
8238                                 pp = &cmdp->next;
8239                         }
8240                 }
8241         }
8242         INT_ON;
8243 }
8244
8245 /*
8246  * Locate a command in the command hash table.  If "add" is nonzero,
8247  * add the command to the table if it is not already present.  The
8248  * variable "lastcmdentry" is set to point to the address of the link
8249  * pointing to the entry, so that delete_cmd_entry can delete the
8250  * entry.
8251  *
8252  * Interrupts must be off if called with add != 0.
8253  */
8254 static struct tblentry **lastcmdentry;
8255
8256 static struct tblentry *
8257 cmdlookup(const char *name, int add)
8258 {
8259         unsigned int hashval;
8260         const char *p;
8261         struct tblentry *cmdp;
8262         struct tblentry **pp;
8263
8264         p = name;
8265         hashval = (unsigned char)*p << 4;
8266         while (*p)
8267                 hashval += (unsigned char)*p++;
8268         hashval &= 0x7FFF;
8269         pp = &cmdtable[hashval % CMDTABLESIZE];
8270         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8271                 if (strcmp(cmdp->cmdname, name) == 0)
8272                         break;
8273                 pp = &cmdp->next;
8274         }
8275         if (add && cmdp == NULL) {
8276                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8277                                 + strlen(name)
8278                                 /* + 1 - already done because
8279                                  * tblentry::cmdname is char[1] */);
8280                 /*cmdp->next = NULL; - ckzalloc did it */
8281                 cmdp->cmdtype = CMDUNKNOWN;
8282                 strcpy(cmdp->cmdname, name);
8283         }
8284         lastcmdentry = pp;
8285         return cmdp;
8286 }
8287
8288 /*
8289  * Delete the command entry returned on the last lookup.
8290  */
8291 static void
8292 delete_cmd_entry(void)
8293 {
8294         struct tblentry *cmdp;
8295
8296         INT_OFF;
8297         cmdp = *lastcmdentry;
8298         *lastcmdentry = cmdp->next;
8299         if (cmdp->cmdtype == CMDFUNCTION)
8300                 freefunc(cmdp->param.func);
8301         free(cmdp);
8302         INT_ON;
8303 }
8304
8305 /*
8306  * Add a new command entry, replacing any existing command entry for
8307  * the same name - except special builtins.
8308  */
8309 static void
8310 addcmdentry(char *name, struct cmdentry *entry)
8311 {
8312         struct tblentry *cmdp;
8313
8314         cmdp = cmdlookup(name, 1);
8315         if (cmdp->cmdtype == CMDFUNCTION) {
8316                 freefunc(cmdp->param.func);
8317         }
8318         cmdp->cmdtype = entry->cmdtype;
8319         cmdp->param = entry->u;
8320         cmdp->rehash = 0;
8321 }
8322
8323 static int FAST_FUNC
8324 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8325 {
8326         struct tblentry **pp;
8327         struct tblentry *cmdp;
8328         int c;
8329         struct cmdentry entry;
8330         char *name;
8331
8332         if (nextopt("r") != '\0') {
8333                 clearcmdentry(0);
8334                 return 0;
8335         }
8336
8337         if (*argptr == NULL) {
8338                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8339                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8340                                 if (cmdp->cmdtype == CMDNORMAL)
8341                                         printentry(cmdp);
8342                         }
8343                 }
8344                 return 0;
8345         }
8346
8347         c = 0;
8348         while ((name = *argptr) != NULL) {
8349                 cmdp = cmdlookup(name, 0);
8350                 if (cmdp != NULL
8351                  && (cmdp->cmdtype == CMDNORMAL
8352                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8353                 ) {
8354                         delete_cmd_entry();
8355                 }
8356                 find_command(name, &entry, DO_ERR, pathval());
8357                 if (entry.cmdtype == CMDUNKNOWN)
8358                         c = 1;
8359                 argptr++;
8360         }
8361         return c;
8362 }
8363
8364 /*
8365  * Called when a cd is done.  Marks all commands so the next time they
8366  * are executed they will be rehashed.
8367  */
8368 static void
8369 hashcd(void)
8370 {
8371         struct tblentry **pp;
8372         struct tblentry *cmdp;
8373
8374         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8375                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8376                         if (cmdp->cmdtype == CMDNORMAL
8377                          || (cmdp->cmdtype == CMDBUILTIN
8378                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8379                              && builtinloc > 0)
8380                         ) {
8381                                 cmdp->rehash = 1;
8382                         }
8383                 }
8384         }
8385 }
8386
8387 /*
8388  * Fix command hash table when PATH changed.
8389  * Called before PATH is changed.  The argument is the new value of PATH;
8390  * pathval() still returns the old value at this point.
8391  * Called with interrupts off.
8392  */
8393 static void FAST_FUNC
8394 changepath(const char *new)
8395 {
8396         const char *old;
8397         int firstchange;
8398         int idx;
8399         int idx_bltin;
8400
8401         old = pathval();
8402         firstchange = 9999;     /* assume no change */
8403         idx = 0;
8404         idx_bltin = -1;
8405         for (;;) {
8406                 if (*old != *new) {
8407                         firstchange = idx;
8408                         if ((*old == '\0' && *new == ':')
8409                          || (*old == ':' && *new == '\0')
8410                         ) {
8411                                 firstchange++;
8412                         }
8413                         old = new;      /* ignore subsequent differences */
8414                 }
8415                 if (*new == '\0')
8416                         break;
8417                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8418                         idx_bltin = idx;
8419                 if (*new == ':')
8420                         idx++;
8421                 new++;
8422                 old++;
8423         }
8424         if (builtinloc < 0 && idx_bltin >= 0)
8425                 builtinloc = idx_bltin;             /* zap builtins */
8426         if (builtinloc >= 0 && idx_bltin < 0)
8427                 firstchange = 0;
8428         clearcmdentry(firstchange);
8429         builtinloc = idx_bltin;
8430 }
8431 enum {
8432         TEOF,
8433         TNL,
8434         TREDIR,
8435         TWORD,
8436         TSEMI,
8437         TBACKGND,
8438         TAND,
8439         TOR,
8440         TPIPE,
8441         TLP,
8442         TRP,
8443         TENDCASE,
8444         TENDBQUOTE,
8445         TNOT,
8446         TCASE,
8447         TDO,
8448         TDONE,
8449         TELIF,
8450         TELSE,
8451         TESAC,
8452         TFI,
8453         TFOR,
8454 #if BASH_FUNCTION
8455         TFUNCTION,
8456 #endif
8457         TIF,
8458         TIN,
8459         TTHEN,
8460         TUNTIL,
8461         TWHILE,
8462         TBEGIN,
8463         TEND
8464 };
8465 typedef smallint token_id_t;
8466
8467 /* Nth bit indicates if token marks the end of a list */
8468 enum {
8469         tokendlist = 0
8470         /*  0 */ | (1u << TEOF)
8471         /*  1 */ | (0u << TNL)
8472         /*  2 */ | (0u << TREDIR)
8473         /*  3 */ | (0u << TWORD)
8474         /*  4 */ | (0u << TSEMI)
8475         /*  5 */ | (0u << TBACKGND)
8476         /*  6 */ | (0u << TAND)
8477         /*  7 */ | (0u << TOR)
8478         /*  8 */ | (0u << TPIPE)
8479         /*  9 */ | (0u << TLP)
8480         /* 10 */ | (1u << TRP)
8481         /* 11 */ | (1u << TENDCASE)
8482         /* 12 */ | (1u << TENDBQUOTE)
8483         /* 13 */ | (0u << TNOT)
8484         /* 14 */ | (0u << TCASE)
8485         /* 15 */ | (1u << TDO)
8486         /* 16 */ | (1u << TDONE)
8487         /* 17 */ | (1u << TELIF)
8488         /* 18 */ | (1u << TELSE)
8489         /* 19 */ | (1u << TESAC)
8490         /* 20 */ | (1u << TFI)
8491         /* 21 */ | (0u << TFOR)
8492 #if BASH_FUNCTION
8493         /* 22 */ | (0u << TFUNCTION)
8494 #endif
8495         /* 23 */ | (0u << TIF)
8496         /* 24 */ | (0u << TIN)
8497         /* 25 */ | (1u << TTHEN)
8498         /* 26 */ | (0u << TUNTIL)
8499         /* 27 */ | (0u << TWHILE)
8500         /* 28 */ | (0u << TBEGIN)
8501         /* 29 */ | (1u << TEND)
8502         , /* thus far 29 bits used */
8503 };
8504
8505 static const char *const tokname_array[] = {
8506         "end of file",
8507         "newline",
8508         "redirection",
8509         "word",
8510         ";",
8511         "&",
8512         "&&",
8513         "||",
8514         "|",
8515         "(",
8516         ")",
8517         ";;",
8518         "`",
8519 #define KWDOFFSET 13
8520         /* the following are keywords */
8521         "!",
8522         "case",
8523         "do",
8524         "done",
8525         "elif",
8526         "else",
8527         "esac",
8528         "fi",
8529         "for",
8530 #if BASH_FUNCTION
8531         "function",
8532 #endif
8533         "if",
8534         "in",
8535         "then",
8536         "until",
8537         "while",
8538         "{",
8539         "}",
8540 };
8541
8542 /* Wrapper around strcmp for qsort/bsearch/... */
8543 static int
8544 pstrcmp(const void *a, const void *b)
8545 {
8546         return strcmp((char*)a, *(char**)b);
8547 }
8548
8549 static const char *const *
8550 findkwd(const char *s)
8551 {
8552         return bsearch(s, tokname_array + KWDOFFSET,
8553                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8554                         sizeof(tokname_array[0]), pstrcmp);
8555 }
8556
8557 /*
8558  * Locate and print what a word is...
8559  */
8560 static int
8561 describe_command(char *command, const char *path, int describe_command_verbose)
8562 {
8563         struct cmdentry entry;
8564 #if ENABLE_ASH_ALIAS
8565         const struct alias *ap;
8566 #endif
8567
8568         path = path ? path : pathval();
8569
8570         if (describe_command_verbose) {
8571                 out1str(command);
8572         }
8573
8574         /* First look at the keywords */
8575         if (findkwd(command)) {
8576                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8577                 goto out;
8578         }
8579
8580 #if ENABLE_ASH_ALIAS
8581         /* Then look at the aliases */
8582         ap = lookupalias(command, 0);
8583         if (ap != NULL) {
8584                 if (!describe_command_verbose) {
8585                         out1str("alias ");
8586                         printalias(ap);
8587                         return 0;
8588                 }
8589                 out1fmt(" is an alias for %s", ap->val);
8590                 goto out;
8591         }
8592 #endif
8593         /* Brute force */
8594         find_command(command, &entry, DO_ABS, path);
8595
8596         switch (entry.cmdtype) {
8597         case CMDNORMAL: {
8598                 int j = entry.u.index;
8599                 char *p;
8600                 if (j < 0) {
8601                         p = command;
8602                 } else {
8603                         do {
8604                                 p = path_advance(&path, command);
8605                                 stunalloc(p);
8606                         } while (--j >= 0);
8607                 }
8608                 if (describe_command_verbose) {
8609                         out1fmt(" is %s", p);
8610                 } else {
8611                         out1str(p);
8612                 }
8613                 break;
8614         }
8615
8616         case CMDFUNCTION:
8617                 if (describe_command_verbose) {
8618                         /*out1str(" is a shell function");*/
8619                         out1str(" is a function"); /* bash says this */
8620                 } else {
8621                         out1str(command);
8622                 }
8623                 break;
8624
8625         case CMDBUILTIN:
8626                 if (describe_command_verbose) {
8627                         out1fmt(" is a %sshell builtin",
8628                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8629                                         "special " : nullstr
8630                         );
8631                 } else {
8632                         out1str(command);
8633                 }
8634                 break;
8635
8636         default:
8637                 if (describe_command_verbose) {
8638                         out1str(": not found\n");
8639                 }
8640                 return 127;
8641         }
8642  out:
8643         out1str("\n");
8644         return 0;
8645 }
8646
8647 static int FAST_FUNC
8648 typecmd(int argc UNUSED_PARAM, char **argv)
8649 {
8650         int i = 1;
8651         int err = 0;
8652         int verbose = 1;
8653
8654         /* type -p ... ? (we don't bother checking for 'p') */
8655         if (argv[1] && argv[1][0] == '-') {
8656                 i++;
8657                 verbose = 0;
8658         }
8659         while (argv[i]) {
8660                 err |= describe_command(argv[i++], NULL, verbose);
8661         }
8662         return err;
8663 }
8664
8665 #if ENABLE_ASH_CMDCMD
8666 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8667 static char **
8668 parse_command_args(char **argv, const char **path)
8669 {
8670         char *cp, c;
8671
8672         for (;;) {
8673                 cp = *++argv;
8674                 if (!cp)
8675                         return NULL;
8676                 if (*cp++ != '-')
8677                         break;
8678                 c = *cp++;
8679                 if (!c)
8680                         break;
8681                 if (c == '-' && !*cp) {
8682                         if (!*++argv)
8683                                 return NULL;
8684                         break;
8685                 }
8686                 do {
8687                         switch (c) {
8688                         case 'p':
8689                                 *path = bb_default_path;
8690                                 break;
8691                         default:
8692                                 /* run 'typecmd' for other options */
8693                                 return NULL;
8694                         }
8695                         c = *cp++;
8696                 } while (c);
8697         }
8698         return argv;
8699 }
8700
8701 static int FAST_FUNC
8702 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8703 {
8704         char *cmd;
8705         int c;
8706         enum {
8707                 VERIFY_BRIEF = 1,
8708                 VERIFY_VERBOSE = 2,
8709         } verify = 0;
8710         const char *path = NULL;
8711
8712         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8713          * never reaches this function.
8714          */
8715
8716         while ((c = nextopt("pvV")) != '\0')
8717                 if (c == 'V')
8718                         verify |= VERIFY_VERBOSE;
8719                 else if (c == 'v')
8720                         /*verify |= VERIFY_BRIEF*/;
8721 #if DEBUG
8722                 else if (c != 'p')
8723                         abort();
8724 #endif
8725                 else
8726                         path = bb_default_path;
8727
8728         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8729         cmd = *argptr;
8730         if (/*verify && */ cmd)
8731                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8732
8733         return 0;
8734 }
8735 #endif
8736
8737
8738 /*static int funcblocksize;     // size of structures in function */
8739 /*static int funcstringsize;    // size of strings in node */
8740 static void *funcblock;         /* block to allocate function from */
8741 static char *funcstring_end;    /* end of block to allocate strings from */
8742
8743 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8744         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8745         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8746         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8747         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8748         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8749         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8750         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8751         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8752         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8753         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8754         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8755         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8756         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8757         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8758         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8759         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8760         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8761 #if BASH_REDIR_OUTPUT
8762         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8763 #endif
8764         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8765         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8766         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8767         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8768         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8769         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8770         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8771         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8772         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8773 };
8774
8775 static int calcsize(int funcblocksize, union node *n);
8776
8777 static int
8778 sizenodelist(int funcblocksize, struct nodelist *lp)
8779 {
8780         while (lp) {
8781                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8782                 funcblocksize = calcsize(funcblocksize, lp->n);
8783                 lp = lp->next;
8784         }
8785         return funcblocksize;
8786 }
8787
8788 static int
8789 calcsize(int funcblocksize, union node *n)
8790 {
8791         if (n == NULL)
8792                 return funcblocksize;
8793         funcblocksize += nodesize[n->type];
8794         switch (n->type) {
8795         case NCMD:
8796                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8797                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8798                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8799                 break;
8800         case NPIPE:
8801                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8802                 break;
8803         case NREDIR:
8804         case NBACKGND:
8805         case NSUBSHELL:
8806                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8807                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8808                 break;
8809         case NAND:
8810         case NOR:
8811         case NSEMI:
8812         case NWHILE:
8813         case NUNTIL:
8814                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8815                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8816                 break;
8817         case NIF:
8818                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8819                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8820                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8821                 break;
8822         case NFOR:
8823                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8824                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8825                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8826                 break;
8827         case NCASE:
8828                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8829                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8830                 break;
8831         case NCLIST:
8832                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8833                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8834                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8835                 break;
8836         case NDEFUN:
8837                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8838                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8839                 break;
8840         case NARG:
8841                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8842                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8843                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8844                 break;
8845         case NTO:
8846 #if BASH_REDIR_OUTPUT
8847         case NTO2:
8848 #endif
8849         case NCLOBBER:
8850         case NFROM:
8851         case NFROMTO:
8852         case NAPPEND:
8853                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8854                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8855                 break;
8856         case NTOFD:
8857         case NFROMFD:
8858                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8859                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8860         break;
8861         case NHERE:
8862         case NXHERE:
8863                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8864                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8865                 break;
8866         case NNOT:
8867                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8868                 break;
8869         };
8870         return funcblocksize;
8871 }
8872
8873 static char *
8874 nodeckstrdup(char *s)
8875 {
8876         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8877         return strcpy(funcstring_end, s);
8878 }
8879
8880 static union node *copynode(union node *);
8881
8882 static struct nodelist *
8883 copynodelist(struct nodelist *lp)
8884 {
8885         struct nodelist *start;
8886         struct nodelist **lpp;
8887
8888         lpp = &start;
8889         while (lp) {
8890                 *lpp = funcblock;
8891                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8892                 (*lpp)->n = copynode(lp->n);
8893                 lp = lp->next;
8894                 lpp = &(*lpp)->next;
8895         }
8896         *lpp = NULL;
8897         return start;
8898 }
8899
8900 static union node *
8901 copynode(union node *n)
8902 {
8903         union node *new;
8904
8905         if (n == NULL)
8906                 return NULL;
8907         new = funcblock;
8908         funcblock = (char *) funcblock + nodesize[n->type];
8909
8910         switch (n->type) {
8911         case NCMD:
8912                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8913                 new->ncmd.args = copynode(n->ncmd.args);
8914                 new->ncmd.assign = copynode(n->ncmd.assign);
8915                 new->ncmd.linno = n->ncmd.linno;
8916                 break;
8917         case NPIPE:
8918                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8919                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8920                 break;
8921         case NREDIR:
8922         case NBACKGND:
8923         case NSUBSHELL:
8924                 new->nredir.redirect = copynode(n->nredir.redirect);
8925                 new->nredir.n = copynode(n->nredir.n);
8926                 new->nredir.linno = n->nredir.linno;
8927                 break;
8928         case NAND:
8929         case NOR:
8930         case NSEMI:
8931         case NWHILE:
8932         case NUNTIL:
8933                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8934                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8935                 break;
8936         case NIF:
8937                 new->nif.elsepart = copynode(n->nif.elsepart);
8938                 new->nif.ifpart = copynode(n->nif.ifpart);
8939                 new->nif.test = copynode(n->nif.test);
8940                 break;
8941         case NFOR:
8942                 new->nfor.var = nodeckstrdup(n->nfor.var);
8943                 new->nfor.body = copynode(n->nfor.body);
8944                 new->nfor.args = copynode(n->nfor.args);
8945                 new->nfor.linno = n->nfor.linno;
8946                 break;
8947         case NCASE:
8948                 new->ncase.cases = copynode(n->ncase.cases);
8949                 new->ncase.expr = copynode(n->ncase.expr);
8950                 new->ncase.linno = n->ncase.linno;
8951                 break;
8952         case NCLIST:
8953                 new->nclist.body = copynode(n->nclist.body);
8954                 new->nclist.pattern = copynode(n->nclist.pattern);
8955                 new->nclist.next = copynode(n->nclist.next);
8956                 break;
8957         case NDEFUN:
8958                 new->ndefun.body = copynode(n->ndefun.body);
8959                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8960                 new->ndefun.linno = n->ndefun.linno;
8961                 break;
8962         case NARG:
8963                 new->narg.backquote = copynodelist(n->narg.backquote);
8964                 new->narg.text = nodeckstrdup(n->narg.text);
8965                 new->narg.next = copynode(n->narg.next);
8966                 break;
8967         case NTO:
8968 #if BASH_REDIR_OUTPUT
8969         case NTO2:
8970 #endif
8971         case NCLOBBER:
8972         case NFROM:
8973         case NFROMTO:
8974         case NAPPEND:
8975                 new->nfile.fname = copynode(n->nfile.fname);
8976                 new->nfile.fd = n->nfile.fd;
8977                 new->nfile.next = copynode(n->nfile.next);
8978                 break;
8979         case NTOFD:
8980         case NFROMFD:
8981                 new->ndup.vname = copynode(n->ndup.vname);
8982                 new->ndup.dupfd = n->ndup.dupfd;
8983                 new->ndup.fd = n->ndup.fd;
8984                 new->ndup.next = copynode(n->ndup.next);
8985                 break;
8986         case NHERE:
8987         case NXHERE:
8988                 new->nhere.doc = copynode(n->nhere.doc);
8989                 new->nhere.fd = n->nhere.fd;
8990                 new->nhere.next = copynode(n->nhere.next);
8991                 break;
8992         case NNOT:
8993                 new->nnot.com = copynode(n->nnot.com);
8994                 break;
8995         };
8996         new->type = n->type;
8997         return new;
8998 }
8999
9000 /*
9001  * Make a copy of a parse tree.
9002  */
9003 static struct funcnode *
9004 copyfunc(union node *n)
9005 {
9006         struct funcnode *f;
9007         size_t blocksize;
9008
9009         /*funcstringsize = 0;*/
9010         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
9011         f = ckzalloc(blocksize /* + funcstringsize */);
9012         funcblock = (char *) f + offsetof(struct funcnode, n);
9013         funcstring_end = (char *) f + blocksize;
9014         copynode(n);
9015         /* f->count = 0; - ckzalloc did it */
9016         return f;
9017 }
9018
9019 /*
9020  * Define a shell function.
9021  */
9022 static void
9023 defun(union node *func)
9024 {
9025         struct cmdentry entry;
9026
9027         INT_OFF;
9028         entry.cmdtype = CMDFUNCTION;
9029         entry.u.func = copyfunc(func);
9030         addcmdentry(func->ndefun.text, &entry);
9031         INT_ON;
9032 }
9033
9034 /* Reasons for skipping commands (see comment on breakcmd routine) */
9035 #define SKIPBREAK      (1 << 0)
9036 #define SKIPCONT       (1 << 1)
9037 #define SKIPFUNC       (1 << 2)
9038 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
9039 static int skipcount;           /* number of levels to skip */
9040 static int loopnest;            /* current loop nesting level */
9041 static int funcline;            /* starting line number of current function, or 0 if not in a function */
9042
9043 /* Forward decl way out to parsing code - dotrap needs it */
9044 static int evalstring(char *s, int flags);
9045
9046 /* Called to execute a trap.
9047  * Single callsite - at the end of evaltree().
9048  * If we return non-zero, evaltree raises EXEXIT exception.
9049  *
9050  * Perhaps we should avoid entering new trap handlers
9051  * while we are executing a trap handler. [is it a TODO?]
9052  */
9053 static void
9054 dotrap(void)
9055 {
9056         uint8_t *g;
9057         int sig;
9058         uint8_t last_status;
9059
9060         if (!pending_sig)
9061                 return;
9062
9063         last_status = exitstatus;
9064         pending_sig = 0;
9065         barrier();
9066
9067         TRACE(("dotrap entered\n"));
9068         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9069                 char *p;
9070
9071                 if (!*g)
9072                         continue;
9073
9074                 if (evalskip) {
9075                         pending_sig = sig;
9076                         break;
9077                 }
9078
9079                 p = trap[sig];
9080                 /* non-trapped SIGINT is handled separately by raise_interrupt,
9081                  * don't upset it by resetting gotsig[SIGINT-1] */
9082                 if (sig == SIGINT && !p)
9083                         continue;
9084
9085                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9086                 *g = 0;
9087                 if (!p)
9088                         continue;
9089                 evalstring(p, 0);
9090         }
9091         exitstatus = last_status;
9092         TRACE(("dotrap returns\n"));
9093 }
9094
9095 /* forward declarations - evaluation is fairly recursive business... */
9096 static int evalloop(union node *, int);
9097 static int evalfor(union node *, int);
9098 static int evalcase(union node *, int);
9099 static int evalsubshell(union node *, int);
9100 static void expredir(union node *);
9101 static int evalpipe(union node *, int);
9102 static int evalcommand(union node *, int);
9103 static int evalbltin(const struct builtincmd *, int, char **, int);
9104 static void prehash(union node *);
9105
9106 /*
9107  * Evaluate a parse tree.  The value is left in the global variable
9108  * exitstatus.
9109  */
9110 static int
9111 evaltree(union node *n, int flags)
9112 {
9113         int checkexit = 0;
9114         int (*evalfn)(union node *, int);
9115         struct stackmark smark;
9116         int status = 0;
9117
9118         setstackmark(&smark);
9119
9120         if (n == NULL) {
9121                 TRACE(("evaltree(NULL) called\n"));
9122                 goto out;
9123         }
9124         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9125
9126         dotrap();
9127
9128         switch (n->type) {
9129         default:
9130 #if DEBUG
9131                 out1fmt("Node type = %d\n", n->type);
9132                 fflush_all();
9133                 break;
9134 #endif
9135         case NNOT:
9136                 status = !evaltree(n->nnot.com, EV_TESTED);
9137                 goto setstatus;
9138         case NREDIR:
9139                 errlinno = lineno = n->nredir.linno;
9140                 if (funcline)
9141                         lineno -= funcline - 1;
9142                 expredir(n->nredir.redirect);
9143                 pushredir(n->nredir.redirect);
9144                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9145                 if (!status) {
9146                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9147                 }
9148                 if (n->nredir.redirect)
9149                         popredir(/*drop:*/ 0);
9150                 goto setstatus;
9151         case NCMD:
9152                 evalfn = evalcommand;
9153  checkexit:
9154                 if (eflag && !(flags & EV_TESTED))
9155                         checkexit = ~0;
9156                 goto calleval;
9157         case NFOR:
9158                 evalfn = evalfor;
9159                 goto calleval;
9160         case NWHILE:
9161         case NUNTIL:
9162                 evalfn = evalloop;
9163                 goto calleval;
9164         case NSUBSHELL:
9165         case NBACKGND:
9166                 evalfn = evalsubshell;
9167                 goto checkexit;
9168         case NPIPE:
9169                 evalfn = evalpipe;
9170                 goto checkexit;
9171         case NCASE:
9172                 evalfn = evalcase;
9173                 goto calleval;
9174         case NAND:
9175         case NOR:
9176         case NSEMI: {
9177
9178 #if NAND + 1 != NOR
9179 #error NAND + 1 != NOR
9180 #endif
9181 #if NOR + 1 != NSEMI
9182 #error NOR + 1 != NSEMI
9183 #endif
9184                 unsigned is_or = n->type - NAND;
9185                 status = evaltree(
9186                         n->nbinary.ch1,
9187                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9188                 );
9189                 if ((!status) == is_or || evalskip)
9190                         break;
9191                 n = n->nbinary.ch2;
9192  evaln:
9193                 evalfn = evaltree;
9194  calleval:
9195                 status = evalfn(n, flags);
9196                 goto setstatus;
9197         }
9198         case NIF:
9199                 status = evaltree(n->nif.test, EV_TESTED);
9200                 if (evalskip)
9201                         break;
9202                 if (!status) {
9203                         n = n->nif.ifpart;
9204                         goto evaln;
9205                 }
9206                 if (n->nif.elsepart) {
9207                         n = n->nif.elsepart;
9208                         goto evaln;
9209                 }
9210                 status = 0;
9211                 goto setstatus;
9212         case NDEFUN:
9213                 defun(n);
9214                 /* Not necessary. To test it:
9215                  * "false; f() { qwerty; }; echo $?" should print 0.
9216                  */
9217                 /* status = 0; */
9218  setstatus:
9219                 exitstatus = status;
9220                 break;
9221         }
9222  out:
9223         /* Order of checks below is important:
9224          * signal handlers trigger before exit caused by "set -e".
9225          */
9226         dotrap();
9227
9228         if (checkexit & status)
9229                 raise_exception(EXEXIT);
9230         if (flags & EV_EXIT)
9231                 raise_exception(EXEXIT);
9232
9233         popstackmark(&smark);
9234         TRACE(("leaving evaltree (no interrupts)\n"));
9235         return exitstatus;
9236 }
9237
9238 static int
9239 skiploop(void)
9240 {
9241         int skip = evalskip;
9242
9243         switch (skip) {
9244         case 0:
9245                 break;
9246         case SKIPBREAK:
9247         case SKIPCONT:
9248                 if (--skipcount <= 0) {
9249                         evalskip = 0;
9250                         break;
9251                 }
9252                 skip = SKIPBREAK;
9253                 break;
9254         }
9255         return skip;
9256 }
9257
9258 static int
9259 evalloop(union node *n, int flags)
9260 {
9261         int skip;
9262         int status;
9263
9264         loopnest++;
9265         status = 0;
9266         flags &= EV_TESTED;
9267         do {
9268                 int i;
9269
9270                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9271                 skip = skiploop();
9272                 if (skip == SKIPFUNC)
9273                         status = i;
9274                 if (skip)
9275                         continue;
9276                 if (n->type != NWHILE)
9277                         i = !i;
9278                 if (i != 0)
9279                         break;
9280                 status = evaltree(n->nbinary.ch2, flags);
9281                 skip = skiploop();
9282         } while (!(skip & ~SKIPCONT));
9283         loopnest--;
9284
9285         return status;
9286 }
9287
9288 static int
9289 evalfor(union node *n, int flags)
9290 {
9291         struct arglist arglist;
9292         union node *argp;
9293         struct strlist *sp;
9294         int status = 0;
9295
9296         errlinno = lineno = n->ncase.linno;
9297         if (funcline)
9298                 lineno -= funcline - 1;
9299
9300         arglist.list = NULL;
9301         arglist.lastp = &arglist.list;
9302         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9303                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9304         }
9305         *arglist.lastp = NULL;
9306
9307         loopnest++;
9308         flags &= EV_TESTED;
9309         for (sp = arglist.list; sp; sp = sp->next) {
9310                 setvar0(n->nfor.var, sp->text);
9311                 status = evaltree(n->nfor.body, flags);
9312                 if (skiploop() & ~SKIPCONT)
9313                         break;
9314         }
9315         loopnest--;
9316
9317         return status;
9318 }
9319
9320 static int
9321 evalcase(union node *n, int flags)
9322 {
9323         union node *cp;
9324         union node *patp;
9325         struct arglist arglist;
9326         int status = 0;
9327
9328         errlinno = lineno = n->ncase.linno;
9329         if (funcline)
9330                 lineno -= funcline - 1;
9331
9332         arglist.list = NULL;
9333         arglist.lastp = &arglist.list;
9334         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9335         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9336                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9337                         if (casematch(patp, arglist.list->text)) {
9338                                 /* Ensure body is non-empty as otherwise
9339                                  * EV_EXIT may prevent us from setting the
9340                                  * exit status.
9341                                  */
9342                                 if (evalskip == 0 && cp->nclist.body) {
9343                                         status = evaltree(cp->nclist.body, flags);
9344                                 }
9345                                 goto out;
9346                         }
9347                 }
9348         }
9349  out:
9350         return status;
9351 }
9352
9353 /*
9354  * Kick off a subshell to evaluate a tree.
9355  */
9356 static int
9357 evalsubshell(union node *n, int flags)
9358 {
9359         struct job *jp;
9360         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9361         int status;
9362
9363         errlinno = lineno = n->nredir.linno;
9364         if (funcline)
9365                 lineno -= funcline - 1;
9366
9367         expredir(n->nredir.redirect);
9368         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9369                 goto nofork;
9370         INT_OFF;
9371         if (backgnd == FORK_FG)
9372                 get_tty_state();
9373         jp = makejob(/*n,*/ 1);
9374         if (forkshell(jp, n, backgnd) == 0) {
9375                 /* child */
9376                 INT_ON;
9377                 flags |= EV_EXIT;
9378                 if (backgnd)
9379                         flags &= ~EV_TESTED;
9380  nofork:
9381                 redirect(n->nredir.redirect, 0);
9382                 evaltreenr(n->nredir.n, flags);
9383                 /* never returns */
9384         }
9385         /* parent */
9386         status = 0;
9387         if (backgnd == FORK_FG)
9388                 status = waitforjob(jp);
9389         INT_ON;
9390         return status;
9391 }
9392
9393 /*
9394  * Compute the names of the files in a redirection list.
9395  */
9396 static void fixredir(union node *, const char *, int);
9397 static void
9398 expredir(union node *n)
9399 {
9400         union node *redir;
9401
9402         for (redir = n; redir; redir = redir->nfile.next) {
9403                 struct arglist fn;
9404
9405                 fn.list = NULL;
9406                 fn.lastp = &fn.list;
9407                 switch (redir->type) {
9408                 case NFROMTO:
9409                 case NFROM:
9410                 case NTO:
9411 #if BASH_REDIR_OUTPUT
9412                 case NTO2:
9413 #endif
9414                 case NCLOBBER:
9415                 case NAPPEND:
9416                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9417                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9418 #if BASH_REDIR_OUTPUT
9419  store_expfname:
9420 #endif
9421 #if 0
9422 // By the design of stack allocator, the loop of this kind:
9423 //      while true; do while true; do break; done </dev/null; done
9424 // will look like a memory leak: ash plans to free expfname's
9425 // of "/dev/null" as soon as it finishes running the loop
9426 // (in this case, never).
9427 // This "fix" is wrong:
9428                         if (redir->nfile.expfname)
9429                                 stunalloc(redir->nfile.expfname);
9430 // It results in corrupted state of stacked allocations.
9431 #endif
9432                         redir->nfile.expfname = fn.list->text;
9433                         break;
9434                 case NFROMFD:
9435                 case NTOFD: /* >& */
9436                         if (redir->ndup.vname) {
9437                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9438                                 if (fn.list == NULL)
9439                                         ash_msg_and_raise_error("redir error");
9440 #if BASH_REDIR_OUTPUT
9441 //FIXME: we used expandarg with different args!
9442                                 if (!isdigit_str9(fn.list->text)) {
9443                                         /* >&file, not >&fd */
9444                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9445                                                 ash_msg_and_raise_error("redir error");
9446                                         redir->type = NTO2;
9447                                         goto store_expfname;
9448                                 }
9449 #endif
9450                                 fixredir(redir, fn.list->text, 1);
9451                         }
9452                         break;
9453                 }
9454         }
9455 }
9456
9457 /*
9458  * Evaluate a pipeline.  All the processes in the pipeline are children
9459  * of the process creating the pipeline.  (This differs from some versions
9460  * of the shell, which make the last process in a pipeline the parent
9461  * of all the rest.)
9462  */
9463 static int
9464 evalpipe(union node *n, int flags)
9465 {
9466         struct job *jp;
9467         struct nodelist *lp;
9468         int pipelen;
9469         int prevfd;
9470         int pip[2];
9471         int status = 0;
9472
9473         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9474         pipelen = 0;
9475         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9476                 pipelen++;
9477         flags |= EV_EXIT;
9478         INT_OFF;
9479         if (n->npipe.pipe_backgnd == 0)
9480                 get_tty_state();
9481         jp = makejob(/*n,*/ pipelen);
9482         prevfd = -1;
9483         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9484                 prehash(lp->n);
9485                 pip[1] = -1;
9486                 if (lp->next) {
9487                         if (pipe(pip) < 0) {
9488                                 close(prevfd);
9489                                 ash_msg_and_raise_perror("can't create pipe");
9490                         }
9491                 }
9492                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9493                         /* child */
9494                         INT_ON;
9495                         if (pip[1] >= 0) {
9496                                 close(pip[0]);
9497                         }
9498                         if (prevfd > 0) {
9499                                 dup2(prevfd, 0);
9500                                 close(prevfd);
9501                         }
9502                         if (pip[1] > 1) {
9503                                 dup2(pip[1], 1);
9504                                 close(pip[1]);
9505                         }
9506                         evaltreenr(lp->n, flags);
9507                         /* never returns */
9508                 }
9509                 /* parent */
9510                 if (prevfd >= 0)
9511                         close(prevfd);
9512                 prevfd = pip[0];
9513                 /* Don't want to trigger debugging */
9514                 if (pip[1] != -1)
9515                         close(pip[1]);
9516         }
9517         if (n->npipe.pipe_backgnd == 0) {
9518                 status = waitforjob(jp);
9519                 TRACE(("evalpipe:  job done exit status %d\n", status));
9520         }
9521         INT_ON;
9522
9523         return status;
9524 }
9525
9526 /*
9527  * Controls whether the shell is interactive or not.
9528  */
9529 static void
9530 setinteractive(int on)
9531 {
9532         static smallint is_interactive;
9533
9534         if (++on == is_interactive)
9535                 return;
9536         is_interactive = on;
9537         setsignal(SIGINT);
9538         setsignal(SIGQUIT);
9539         setsignal(SIGTERM);
9540         if (is_interactive > 1) {
9541 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9542                 /* Looks like they want an interactive shell */
9543                 static smallint did_banner;
9544
9545                 if (!did_banner) {
9546                         /* note: ash and hush share this string */
9547                         out1fmt("\n\n%s %s\n"
9548                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9549                                 "\n",
9550                                 bb_banner,
9551                                 "built-in shell (ash)"
9552                         );
9553                         did_banner = 1;
9554                 }
9555 #endif
9556 #if ENABLE_FEATURE_EDITING
9557                 if (!line_input_state)
9558                         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9559 #endif
9560         }
9561 }
9562
9563 static void
9564 optschanged(void)
9565 {
9566 #if DEBUG
9567         opentrace();
9568 #endif
9569         setinteractive(iflag);
9570         setjobctl(mflag);
9571 #if ENABLE_FEATURE_EDITING_VI
9572         if (line_input_state) {
9573                 if (viflag)
9574                         line_input_state->flags |= VI_MODE;
9575                 else
9576                         line_input_state->flags &= ~VI_MODE;
9577         }
9578 #else
9579         viflag = 0; /* forcibly keep the option off */
9580 #endif
9581 }
9582
9583 struct localvar_list {
9584         struct localvar_list *next;
9585         struct localvar *lv;
9586 };
9587
9588 static struct localvar_list *localvar_stack;
9589
9590 /*
9591  * Called after a function returns.
9592  * Interrupts must be off.
9593  */
9594 static void
9595 poplocalvars(int keep)
9596 {
9597         struct localvar_list *ll;
9598         struct localvar *lvp, *next;
9599         struct var *vp;
9600
9601         INT_OFF;
9602         ll = localvar_stack;
9603         localvar_stack = ll->next;
9604
9605         next = ll->lv;
9606         free(ll);
9607
9608         while ((lvp = next) != NULL) {
9609                 next = lvp->next;
9610                 vp = lvp->vp;
9611                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9612                 if (keep) {
9613                         int bits = VSTRFIXED;
9614
9615                         if (lvp->flags != VUNSET) {
9616                                 if (vp->var_text == lvp->text)
9617                                         bits |= VTEXTFIXED;
9618                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9619                                         free((char*)lvp->text);
9620                         }
9621
9622                         vp->flags &= ~bits;
9623                         vp->flags |= (lvp->flags & bits);
9624
9625                         if ((vp->flags &
9626                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9627                                 unsetvar(vp->var_text);
9628                 } else if (vp == NULL) {        /* $- saved */
9629                         memcpy(optlist, lvp->text, sizeof(optlist));
9630                         free((char*)lvp->text);
9631                         optschanged();
9632                 } else if (lvp->flags == VUNSET) {
9633                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9634                         unsetvar(vp->var_text);
9635                 } else {
9636                         if (vp->var_func)
9637                                 vp->var_func(var_end(lvp->text));
9638                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9639                                 free((char*)vp->var_text);
9640                         vp->flags = lvp->flags;
9641                         vp->var_text = lvp->text;
9642                 }
9643                 free(lvp);
9644         }
9645         INT_ON;
9646 }
9647
9648 /*
9649  * Create a new localvar environment.
9650  */
9651 static struct localvar_list *
9652 pushlocalvars(void)
9653 {
9654         struct localvar_list *ll;
9655
9656         INT_OFF;
9657         ll = ckzalloc(sizeof(*ll));
9658         /*ll->lv = NULL; - zalloc did it */
9659         ll->next = localvar_stack;
9660         localvar_stack = ll;
9661         INT_ON;
9662
9663         return ll->next;
9664 }
9665
9666 static void
9667 unwindlocalvars(struct localvar_list *stop)
9668 {
9669         while (localvar_stack != stop)
9670                 poplocalvars(0);
9671 }
9672
9673 static int
9674 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9675 {
9676         volatile struct shparam saveparam;
9677         struct jmploc *volatile savehandler;
9678         struct jmploc jmploc;
9679         int e;
9680         int savefuncline;
9681
9682         saveparam = shellparam;
9683         savefuncline = funcline;
9684         savehandler = exception_handler;
9685         e = setjmp(jmploc.loc);
9686         if (e) {
9687                 goto funcdone;
9688         }
9689         INT_OFF;
9690         exception_handler = &jmploc;
9691         shellparam.malloced = 0;
9692         func->count++;
9693         funcline = func->n.ndefun.linno;
9694         INT_ON;
9695         shellparam.nparam = argc - 1;
9696         shellparam.p = argv + 1;
9697 #if ENABLE_ASH_GETOPTS
9698         shellparam.optind = 1;
9699         shellparam.optoff = -1;
9700 #endif
9701         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9702  funcdone:
9703         INT_OFF;
9704         funcline = savefuncline;
9705         freefunc(func);
9706         freeparam(&shellparam);
9707         shellparam = saveparam;
9708         exception_handler = savehandler;
9709         INT_ON;
9710         evalskip &= ~SKIPFUNC;
9711         return e;
9712 }
9713
9714 /*
9715  * Make a variable a local variable.  When a variable is made local, it's
9716  * value and flags are saved in a localvar structure.  The saved values
9717  * will be restored when the shell function returns.  We handle the name
9718  * "-" as a special case: it makes changes to "set +-options" local
9719  * (options will be restored on return from the function).
9720  */
9721 static void
9722 mklocal(char *name)
9723 {
9724         struct localvar *lvp;
9725         struct var **vpp;
9726         struct var *vp;
9727         char *eq = strchr(name, '=');
9728
9729         INT_OFF;
9730         /* Cater for duplicate "local". Examples:
9731          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9732          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9733          */
9734         lvp = localvar_stack->lv;
9735         while (lvp) {
9736                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9737                         if (eq)
9738                                 setvareq(name, 0);
9739                         /* else:
9740                          * it's a duplicate "local VAR" declaration, do nothing
9741                          */
9742                         goto ret;
9743                 }
9744                 lvp = lvp->next;
9745         }
9746
9747         lvp = ckzalloc(sizeof(*lvp));
9748         if (LONE_DASH(name)) {
9749                 char *p;
9750                 p = ckmalloc(sizeof(optlist));
9751                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9752                 vp = NULL;
9753         } else {
9754                 vpp = hashvar(name);
9755                 vp = *findvar(vpp, name);
9756                 if (vp == NULL) {
9757                         /* variable did not exist yet */
9758                         if (eq)
9759                                 vp = setvareq(name, VSTRFIXED);
9760                         else
9761                                 vp = setvar(name, NULL, VSTRFIXED);
9762                         lvp->flags = VUNSET;
9763                 } else {
9764                         lvp->text = vp->var_text;
9765                         lvp->flags = vp->flags;
9766                         /* make sure neither "struct var" nor string gets freed
9767                          * during (un)setting:
9768                          */
9769                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9770                         if (eq)
9771                                 setvareq(name, 0);
9772                         else
9773                                 /* "local VAR" unsets VAR: */
9774                                 setvar0(name, NULL);
9775                 }
9776         }
9777         lvp->vp = vp;
9778         lvp->next = localvar_stack->lv;
9779         localvar_stack->lv = lvp;
9780  ret:
9781         INT_ON;
9782 }
9783
9784 /*
9785  * The "local" command.
9786  */
9787 static int FAST_FUNC
9788 localcmd(int argc UNUSED_PARAM, char **argv)
9789 {
9790         char *name;
9791
9792         if (!localvar_stack)
9793                 ash_msg_and_raise_error("not in a function");
9794
9795         argv = argptr;
9796         while ((name = *argv++) != NULL) {
9797                 mklocal(name);
9798         }
9799         return 0;
9800 }
9801
9802 static int FAST_FUNC
9803 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9804 {
9805         return 1;
9806 }
9807
9808 static int FAST_FUNC
9809 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9810 {
9811         return 0;
9812 }
9813
9814 static int FAST_FUNC
9815 execcmd(int argc UNUSED_PARAM, char **argv)
9816 {
9817         optionarg = NULL;
9818         while (nextopt("a:") != '\0')
9819                 /* nextopt() sets optionarg to "-a ARGV0" */;
9820
9821         argv = argptr;
9822         if (argv[0]) {
9823                 char *prog;
9824
9825                 iflag = 0;              /* exit on error */
9826                 mflag = 0;
9827                 optschanged();
9828                 /* We should set up signals for "exec CMD"
9829                  * the same way as for "CMD" without "exec".
9830                  * But optschanged->setinteractive->setsignal
9831                  * still thought we are a root shell. Therefore, for example,
9832                  * SIGQUIT is still set to IGN. Fix it:
9833                  */
9834                 shlvl++;
9835                 setsignal(SIGQUIT);
9836                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9837                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9838                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9839
9840                 prog = argv[0];
9841                 if (optionarg)
9842                         argv[0] = optionarg;
9843                 shellexec(prog, argv, pathval(), 0);
9844                 /* NOTREACHED */
9845         }
9846         return 0;
9847 }
9848
9849 /*
9850  * The return command.
9851  */
9852 static int FAST_FUNC
9853 returncmd(int argc UNUSED_PARAM, char **argv)
9854 {
9855         /*
9856          * If called outside a function, do what ksh does;
9857          * skip the rest of the file.
9858          */
9859         evalskip = SKIPFUNC;
9860         return argv[1] ? number(argv[1]) : exitstatus;
9861 }
9862
9863 /* Forward declarations for builtintab[] */
9864 static int breakcmd(int, char **) FAST_FUNC;
9865 static int dotcmd(int, char **) FAST_FUNC;
9866 static int evalcmd(int, char **, int) FAST_FUNC;
9867 static int exitcmd(int, char **) FAST_FUNC;
9868 static int exportcmd(int, char **) FAST_FUNC;
9869 #if ENABLE_ASH_GETOPTS
9870 static int getoptscmd(int, char **) FAST_FUNC;
9871 #endif
9872 #if ENABLE_ASH_HELP
9873 static int helpcmd(int, char **) FAST_FUNC;
9874 #endif
9875 #if MAX_HISTORY
9876 static int historycmd(int, char **) FAST_FUNC;
9877 #endif
9878 #if ENABLE_FEATURE_SH_MATH
9879 static int letcmd(int, char **) FAST_FUNC;
9880 #endif
9881 static int readcmd(int, char **) FAST_FUNC;
9882 static int setcmd(int, char **) FAST_FUNC;
9883 static int shiftcmd(int, char **) FAST_FUNC;
9884 static int timescmd(int, char **) FAST_FUNC;
9885 static int trapcmd(int, char **) FAST_FUNC;
9886 static int umaskcmd(int, char **) FAST_FUNC;
9887 static int unsetcmd(int, char **) FAST_FUNC;
9888 static int ulimitcmd(int, char **) FAST_FUNC;
9889
9890 #define BUILTIN_NOSPEC          "0"
9891 #define BUILTIN_SPECIAL         "1"
9892 #define BUILTIN_REGULAR         "2"
9893 #define BUILTIN_SPEC_REG        "3"
9894 #define BUILTIN_ASSIGN          "4"
9895 #define BUILTIN_SPEC_ASSG       "5"
9896 #define BUILTIN_REG_ASSG        "6"
9897 #define BUILTIN_SPEC_REG_ASSG   "7"
9898
9899 /* Stubs for calling non-FAST_FUNC's */
9900 #if ENABLE_ASH_ECHO
9901 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9902 #endif
9903 #if ENABLE_ASH_PRINTF
9904 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9905 #endif
9906 #if ENABLE_ASH_TEST || BASH_TEST2
9907 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9908 #endif
9909
9910 /* Keep these in proper order since it is searched via bsearch() */
9911 static const struct builtincmd builtintab[] = {
9912         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9913         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9914 #if ENABLE_ASH_TEST
9915         { BUILTIN_REGULAR       "["       , testcmd    },
9916 #endif
9917 #if BASH_TEST2
9918         { BUILTIN_REGULAR       "[["      , testcmd    },
9919 #endif
9920 #if ENABLE_ASH_ALIAS
9921         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9922 #endif
9923 #if JOBS
9924         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9925 #endif
9926         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9927         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9928         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9929 #if ENABLE_ASH_CMDCMD
9930         { BUILTIN_REGULAR       "command" , commandcmd },
9931 #endif
9932         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9933 #if ENABLE_ASH_ECHO
9934         { BUILTIN_REGULAR       "echo"    , echocmd    },
9935 #endif
9936         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9937         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9938         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9939         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9940         { BUILTIN_REGULAR       "false"   , falsecmd   },
9941 #if JOBS
9942         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9943 #endif
9944 #if ENABLE_ASH_GETOPTS
9945         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9946 #endif
9947         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9948 #if ENABLE_ASH_HELP
9949         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9950 #endif
9951 #if MAX_HISTORY
9952         { BUILTIN_NOSPEC        "history" , historycmd },
9953 #endif
9954 #if JOBS
9955         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9956         { BUILTIN_REGULAR       "kill"    , killcmd    },
9957 #endif
9958 #if ENABLE_FEATURE_SH_MATH
9959         { BUILTIN_NOSPEC        "let"     , letcmd     },
9960 #endif
9961         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9962 #if ENABLE_ASH_PRINTF
9963         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9964 #endif
9965         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9966         { BUILTIN_REGULAR       "read"    , readcmd    },
9967         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9968         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9969         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9970         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9971 #if BASH_SOURCE
9972         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9973 #endif
9974 #if ENABLE_ASH_TEST
9975         { BUILTIN_REGULAR       "test"    , testcmd    },
9976 #endif
9977         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9978         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9979         { BUILTIN_REGULAR       "true"    , truecmd    },
9980         { BUILTIN_NOSPEC        "type"    , typecmd    },
9981         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9982         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9983 #if ENABLE_ASH_ALIAS
9984         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9985 #endif
9986         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9987         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9988 };
9989
9990 /* Should match the above table! */
9991 #define COMMANDCMD (builtintab + \
9992         /* . : */       2 + \
9993         /* [ */         1 * ENABLE_ASH_TEST + \
9994         /* [[ */        1 * BASH_TEST2 + \
9995         /* alias */     1 * ENABLE_ASH_ALIAS + \
9996         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9997         /* break cd cddir  */   3)
9998 #define EVALCMD (COMMANDCMD + \
9999         /* command */   1 * ENABLE_ASH_CMDCMD + \
10000         /* continue */  1 + \
10001         /* echo */      1 * ENABLE_ASH_ECHO + \
10002         0)
10003 #define EXECCMD (EVALCMD + \
10004         /* eval */      1)
10005
10006 /*
10007  * Search the table of builtin commands.
10008  */
10009 static int
10010 pstrcmp1(const void *a, const void *b)
10011 {
10012         return strcmp((char*)a, *(char**)b + 1);
10013 }
10014 static struct builtincmd *
10015 find_builtin(const char *name)
10016 {
10017         struct builtincmd *bp;
10018
10019         bp = bsearch(
10020                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
10021                 pstrcmp1
10022         );
10023         return bp;
10024 }
10025
10026 /*
10027  * Execute a simple command.
10028  */
10029 static void unwindfiles(struct parsefile *stop);
10030 static int
10031 isassignment(const char *p)
10032 {
10033         const char *q = endofname(p);
10034         if (p == q)
10035                 return 0;
10036         return *q == '=';
10037 }
10038 static int FAST_FUNC
10039 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10040 {
10041         /* Preserve exitstatus of a previous possible redirection
10042          * as POSIX mandates */
10043         return back_exitstatus;
10044 }
10045 static int
10046 evalcommand(union node *cmd, int flags)
10047 {
10048         static const struct builtincmd null_bltin = {
10049                 "\0\0", bltincmd /* why three NULs? */
10050         };
10051         struct localvar_list *localvar_stop;
10052         struct parsefile *file_stop;
10053         struct redirtab *redir_stop;
10054         union node *argp;
10055         struct arglist arglist;
10056         struct arglist varlist;
10057         char **argv;
10058         int argc;
10059         const struct strlist *sp;
10060         struct cmdentry cmdentry;
10061         struct job *jp;
10062         char *lastarg;
10063         const char *path;
10064         int spclbltin;
10065         int status;
10066         char **nargv;
10067         smallint cmd_is_exec;
10068
10069         errlinno = lineno = cmd->ncmd.linno;
10070         if (funcline)
10071                 lineno -= funcline - 1;
10072
10073         /* First expand the arguments. */
10074         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10075         localvar_stop = pushlocalvars();
10076         file_stop = g_parsefile;
10077         back_exitstatus = 0;
10078
10079         cmdentry.cmdtype = CMDBUILTIN;
10080         cmdentry.u.cmd = &null_bltin;
10081         varlist.lastp = &varlist.list;
10082         *varlist.lastp = NULL;
10083         arglist.lastp = &arglist.list;
10084         *arglist.lastp = NULL;
10085
10086         argc = 0;
10087         if (cmd->ncmd.args) {
10088                 struct builtincmd *bcmd;
10089                 smallint pseudovarflag;
10090
10091                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
10092                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
10093
10094                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
10095                         struct strlist **spp;
10096
10097                         spp = arglist.lastp;
10098                         if (pseudovarflag && isassignment(argp->narg.text))
10099                                 expandarg(argp, &arglist, EXP_VARTILDE);
10100                         else
10101                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
10102
10103                         for (sp = *spp; sp; sp = sp->next)
10104                                 argc++;
10105                 }
10106         }
10107
10108         /* Reserve one extra spot at the front for shellexec. */
10109         nargv = stalloc(sizeof(char *) * (argc + 2));
10110         argv = ++nargv;
10111         for (sp = arglist.list; sp; sp = sp->next) {
10112                 TRACE(("evalcommand arg: %s\n", sp->text));
10113                 *nargv++ = sp->text;
10114         }
10115         *nargv = NULL;
10116
10117         lastarg = NULL;
10118         if (iflag && funcline == 0 && argc > 0)
10119                 lastarg = nargv[-1];
10120
10121         expredir(cmd->ncmd.redirect);
10122         redir_stop = pushredir(cmd->ncmd.redirect);
10123         preverrout_fd = 2;
10124         if (BASH_XTRACEFD && xflag) {
10125                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10126                  * we do not emulate this. We only use its value.
10127                  */
10128                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10129                 if (xtracefd && is_number(xtracefd))
10130                         preverrout_fd = atoi(xtracefd);
10131
10132         }
10133         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10134
10135         path = vpath.var_text;
10136         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10137                 struct strlist **spp;
10138                 char *p;
10139
10140                 spp = varlist.lastp;
10141                 expandarg(argp, &varlist, EXP_VARTILDE);
10142
10143                 mklocal((*spp)->text);
10144
10145                 /*
10146                  * Modify the command lookup path, if a PATH= assignment
10147                  * is present
10148                  */
10149                 p = (*spp)->text;
10150                 if (varcmp(p, path) == 0)
10151                         path = p;
10152         }
10153
10154         /* Print the command if xflag is set. */
10155         if (xflag) {
10156                 const char *pfx = "";
10157
10158                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10159
10160                 sp = varlist.list;
10161                 while (sp) {
10162                         char *varval = sp->text;
10163                         char *eq = strchrnul(varval, '=');
10164                         if (*eq)
10165                                 eq++;
10166                         fdprintf(preverrout_fd, "%s%.*s%s",
10167                                 pfx,
10168                                 (int)(eq - varval), varval,
10169                                 maybe_single_quote(eq)
10170                         );
10171                         sp = sp->next;
10172                         pfx = " ";
10173                 }
10174
10175                 sp = arglist.list;
10176                 while (sp) {
10177                         fdprintf(preverrout_fd, "%s%s",
10178                                 pfx,
10179                                 /* always quote if matches reserved word: */
10180                                 findkwd(sp->text)
10181                                 ? single_quote(sp->text)
10182                                 : maybe_single_quote(sp->text)
10183                         );
10184                         sp = sp->next;
10185                         pfx = " ";
10186                 }
10187                 safe_write(preverrout_fd, "\n", 1);
10188         }
10189
10190         cmd_is_exec = 0;
10191         spclbltin = -1;
10192
10193         /* Now locate the command. */
10194         if (argc) {
10195                 int cmd_flag = DO_ERR;
10196 #if ENABLE_ASH_CMDCMD
10197                 const char *oldpath = path + 5;
10198 #endif
10199                 path += 5;
10200                 for (;;) {
10201                         find_command(argv[0], &cmdentry, cmd_flag, path);
10202                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10203                                 flush_stdout_stderr();
10204                                 status = 127;
10205                                 goto bail;
10206                         }
10207
10208                         /* implement bltin and command here */
10209                         if (cmdentry.cmdtype != CMDBUILTIN)
10210                                 break;
10211                         if (spclbltin < 0)
10212                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10213                         if (cmdentry.u.cmd == EXECCMD)
10214                                 cmd_is_exec = 1;
10215 #if ENABLE_ASH_CMDCMD
10216                         if (cmdentry.u.cmd == COMMANDCMD) {
10217                                 path = oldpath;
10218                                 nargv = parse_command_args(argv, &path);
10219                                 if (!nargv)
10220                                         break;
10221                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10222                                  * nargv => "PROG". path is updated if -p.
10223                                  */
10224                                 argc -= nargv - argv;
10225                                 argv = nargv;
10226                                 cmd_flag |= DO_NOFUNC;
10227                         } else
10228 #endif
10229                                 break;
10230                 }
10231         }
10232
10233         if (status) {
10234  bail:
10235                 exitstatus = status;
10236
10237                 /* We have a redirection error. */
10238                 if (spclbltin > 0)
10239                         raise_exception(EXERROR);
10240
10241                 goto out;
10242         }
10243
10244         /* Execute the command. */
10245         switch (cmdentry.cmdtype) {
10246         default: {
10247
10248 #if ENABLE_FEATURE_SH_STANDALONE \
10249  && ENABLE_FEATURE_SH_NOFORK \
10250  && NUM_APPLETS > 1
10251 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10252  *     around run_nofork_applet() call.
10253  * (2) Should this check also be done in forkshell()?
10254  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10255  */
10256                 /* find_command() encodes applet_no as (-2 - applet_no) */
10257                 int applet_no = (- cmdentry.u.index - 2);
10258                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10259                         char **sv_environ;
10260
10261                         INT_OFF;
10262                         sv_environ = environ;
10263                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10264                         /*
10265                          * Run <applet>_main().
10266                          * Signals (^C) can't interrupt here.
10267                          * Otherwise we can mangle stdio or malloc internal state.
10268                          * This makes applets which can run for a long time
10269                          * and/or wait for user input ineligible for NOFORK:
10270                          * for example, "yes" or "rm" (rm -i waits for input).
10271                          */
10272                         status = run_nofork_applet(applet_no, argv);
10273                         environ = sv_environ;
10274                         /*
10275                          * Try enabling NOFORK for "yes" applet.
10276                          * ^C _will_ stop it (write returns EINTR),
10277                          * but this causes stdout FILE to be stuck
10278                          * and needing clearerr(). What if other applets
10279                          * also can get EINTRs? Do we need to switch
10280                          * our signals to SA_RESTART?
10281                          */
10282                         /*clearerr(stdout);*/
10283                         INT_ON;
10284                         break;
10285                 }
10286 #endif
10287                 /* Can we avoid forking? For example, very last command
10288                  * in a script or a subshell does not need forking,
10289                  * we can just exec it.
10290                  */
10291                 if (!(flags & EV_EXIT) || may_have_traps) {
10292                         /* No, forking off a child is necessary */
10293                         INT_OFF;
10294                         get_tty_state();
10295                         jp = makejob(/*cmd,*/ 1);
10296                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10297                                 /* parent */
10298                                 status = waitforjob(jp);
10299                                 INT_ON;
10300                                 TRACE(("forked child exited with %d\n", status));
10301                                 break;
10302                         }
10303                         /* child */
10304                         FORCE_INT_ON;
10305                         /* fall through to exec'ing external program */
10306                 }
10307                 listsetvar(varlist.list, VEXPORT|VSTACK);
10308                 shellexec(argv[0], argv, path, cmdentry.u.index);
10309                 /* NOTREACHED */
10310         } /* default */
10311         case CMDBUILTIN:
10312                 if (spclbltin > 0 || argc == 0) {
10313                         poplocalvars(1);
10314                         if (cmd_is_exec && argc > 1)
10315                                 listsetvar(varlist.list, VEXPORT);
10316                 }
10317
10318                 /* Tight loop with builtins only:
10319                  * "while kill -0 $child; do true; done"
10320                  * will never exit even if $child died, unless we do this
10321                  * to reap the zombie and make kill detect that it's gone: */
10322                 dowait(DOWAIT_NONBLOCK, NULL);
10323
10324                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10325                         if (exception_type == EXERROR && spclbltin <= 0) {
10326                                 FORCE_INT_ON;
10327                                 goto readstatus;
10328                         }
10329  raise:
10330                         longjmp(exception_handler->loc, 1);
10331                 }
10332                 goto readstatus;
10333
10334         case CMDFUNCTION:
10335                 /* See above for the rationale */
10336                 dowait(DOWAIT_NONBLOCK, NULL);
10337                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10338                         goto raise;
10339  readstatus:
10340                 status = exitstatus;
10341                 break;
10342         } /* switch */
10343
10344  out:
10345         if (cmd->ncmd.redirect)
10346                 popredir(/*drop:*/ cmd_is_exec);
10347         unwindredir(redir_stop);
10348         unwindfiles(file_stop);
10349         unwindlocalvars(localvar_stop);
10350         if (lastarg) {
10351                 /* dsl: I think this is intended to be used to support
10352                  * '_' in 'vi' command mode during line editing...
10353                  * However I implemented that within libedit itself.
10354                  */
10355                 setvar0("_", lastarg);
10356         }
10357
10358         return status;
10359 }
10360
10361 static int
10362 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10363 {
10364         char *volatile savecmdname;
10365         struct jmploc *volatile savehandler;
10366         struct jmploc jmploc;
10367         int status;
10368         int i;
10369
10370         savecmdname = commandname;
10371         savehandler = exception_handler;
10372         i = setjmp(jmploc.loc);
10373         if (i)
10374                 goto cmddone;
10375         exception_handler = &jmploc;
10376         commandname = argv[0];
10377         argptr = argv + 1;
10378         optptr = NULL;                  /* initialize nextopt */
10379         if (cmd == EVALCMD)
10380                 status = evalcmd(argc, argv, flags);
10381         else
10382                 status = (*cmd->builtin)(argc, argv);
10383         flush_stdout_stderr();
10384         status |= ferror(stdout);
10385         exitstatus = status;
10386  cmddone:
10387         clearerr(stdout);
10388         commandname = savecmdname;
10389         exception_handler = savehandler;
10390
10391         return i;
10392 }
10393
10394 static int
10395 goodname(const char *p)
10396 {
10397         return endofname(p)[0] == '\0';
10398 }
10399
10400
10401 /*
10402  * Search for a command.  This is called before we fork so that the
10403  * location of the command will be available in the parent as well as
10404  * the child.  The check for "goodname" is an overly conservative
10405  * check that the name will not be subject to expansion.
10406  */
10407 static void
10408 prehash(union node *n)
10409 {
10410         struct cmdentry entry;
10411
10412         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10413                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10414 }
10415
10416
10417 /* ============ Builtin commands
10418  *
10419  * Builtin commands whose functions are closely tied to evaluation
10420  * are implemented here.
10421  */
10422
10423 /*
10424  * Handle break and continue commands.  Break, continue, and return are
10425  * all handled by setting the evalskip flag.  The evaluation routines
10426  * above all check this flag, and if it is set they start skipping
10427  * commands rather than executing them.  The variable skipcount is
10428  * the number of loops to break/continue, or the number of function
10429  * levels to return.  (The latter is always 1.)  It should probably
10430  * be an error to break out of more loops than exist, but it isn't
10431  * in the standard shell so we don't make it one here.
10432  */
10433 static int FAST_FUNC
10434 breakcmd(int argc UNUSED_PARAM, char **argv)
10435 {
10436         int n = argv[1] ? number(argv[1]) : 1;
10437
10438         if (n <= 0)
10439                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10440         if (n > loopnest)
10441                 n = loopnest;
10442         if (n > 0) {
10443                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10444                 skipcount = n;
10445         }
10446         return 0;
10447 }
10448
10449
10450 /*
10451  * This implements the input routines used by the parser.
10452  */
10453
10454 enum {
10455         INPUT_PUSH_FILE = 1,
10456         INPUT_NOFILE_OK = 2,
10457 };
10458
10459 static smallint checkkwd;
10460 /* values of checkkwd variable */
10461 #define CHKALIAS        0x1
10462 #define CHKKWD          0x2
10463 #define CHKNL           0x4
10464 #define CHKEOFMARK      0x8
10465
10466 /*
10467  * Push a string back onto the input at this current parsefile level.
10468  * We handle aliases this way.
10469  */
10470 #if !ENABLE_ASH_ALIAS
10471 #define pushstring(s, ap) pushstring(s)
10472 #endif
10473 static void
10474 pushstring(char *s, struct alias *ap)
10475 {
10476         struct strpush *sp;
10477         int len;
10478
10479         len = strlen(s);
10480         INT_OFF;
10481         if (g_parsefile->strpush) {
10482                 sp = ckzalloc(sizeof(*sp));
10483                 sp->prev = g_parsefile->strpush;
10484         } else {
10485                 sp = &(g_parsefile->basestrpush);
10486         }
10487         g_parsefile->strpush = sp;
10488         sp->prev_string = g_parsefile->next_to_pgetc;
10489         sp->prev_left_in_line = g_parsefile->left_in_line;
10490         sp->unget = g_parsefile->unget;
10491         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10492 #if ENABLE_ASH_ALIAS
10493         sp->ap = ap;
10494         if (ap) {
10495                 ap->flag |= ALIASINUSE;
10496                 sp->string = s;
10497         }
10498 #endif
10499         g_parsefile->next_to_pgetc = s;
10500         g_parsefile->left_in_line = len;
10501         g_parsefile->unget = 0;
10502         INT_ON;
10503 }
10504
10505 static void
10506 popstring(void)
10507 {
10508         struct strpush *sp = g_parsefile->strpush;
10509
10510         INT_OFF;
10511 #if ENABLE_ASH_ALIAS
10512         if (sp->ap) {
10513                 if (g_parsefile->next_to_pgetc[-1] == ' '
10514                  || g_parsefile->next_to_pgetc[-1] == '\t'
10515                 ) {
10516                         checkkwd |= CHKALIAS;
10517                 }
10518                 if (sp->string != sp->ap->val) {
10519                         free(sp->string);
10520                 }
10521                 sp->ap->flag &= ~ALIASINUSE;
10522                 if (sp->ap->flag & ALIASDEAD) {
10523                         unalias(sp->ap->name);
10524                 }
10525         }
10526 #endif
10527         g_parsefile->next_to_pgetc = sp->prev_string;
10528         g_parsefile->left_in_line = sp->prev_left_in_line;
10529         g_parsefile->unget = sp->unget;
10530         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10531         g_parsefile->strpush = sp->prev;
10532         if (sp != &(g_parsefile->basestrpush))
10533                 free(sp);
10534         INT_ON;
10535 }
10536
10537 static int
10538 preadfd(void)
10539 {
10540         int nr;
10541         char *buf = g_parsefile->buf;
10542
10543         g_parsefile->next_to_pgetc = buf;
10544 #if ENABLE_FEATURE_EDITING
10545  retry:
10546         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10547                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10548         else {
10549 # if ENABLE_ASH_IDLE_TIMEOUT
10550                 int timeout = -1;
10551                 const char *tmout_var = lookupvar("TMOUT");
10552                 if (tmout_var) {
10553                         timeout = atoi(tmout_var) * 1000;
10554                         if (timeout <= 0)
10555                                 timeout = -1;
10556                 }
10557                 line_input_state->timeout = timeout;
10558 # endif
10559 # if ENABLE_FEATURE_TAB_COMPLETION
10560                 line_input_state->path_lookup = pathval();
10561 # endif
10562                 reinit_unicode_for_ash();
10563                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10564                 if (nr == 0) {
10565                         /* ^C pressed, "convert" to SIGINT */
10566                         write(STDOUT_FILENO, "^C", 2);
10567                         if (trap[SIGINT]) {
10568                                 buf[0] = '\n';
10569                                 buf[1] = '\0';
10570                                 raise(SIGINT);
10571                                 return 1;
10572                         }
10573                         exitstatus = 128 + SIGINT;
10574                         bb_putchar('\n');
10575                         goto retry;
10576                 }
10577                 if (nr < 0) {
10578                         if (errno == 0) {
10579                                 /* Ctrl+D pressed */
10580                                 nr = 0;
10581                         }
10582 # if ENABLE_ASH_IDLE_TIMEOUT
10583                         else if (errno == EAGAIN && timeout > 0) {
10584                                 puts("\007timed out waiting for input: auto-logout");
10585                                 exitshell();
10586                         }
10587 # endif
10588                 }
10589         }
10590 #else
10591         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10592 #endif
10593
10594 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10595         if (nr < 0) {
10596                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10597                         int flags = fcntl(0, F_GETFL);
10598                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10599                                 flags &= ~O_NONBLOCK;
10600                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10601                                         out2str("sh: turning off NDELAY mode\n");
10602                                         goto retry;
10603                                 }
10604                         }
10605                 }
10606         }
10607 #endif
10608         return nr;
10609 }
10610
10611 /*
10612  * Refill the input buffer and return the next input character:
10613  *
10614  * 1) If a string was pushed back on the input, pop it;
10615  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10616  *    or we are reading from a string so we can't refill the buffer,
10617  *    return EOF.
10618  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10619  * 4) Process input up to the next newline, deleting nul characters.
10620  */
10621 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10622 #define pgetc_debug(...) ((void)0)
10623 static int pgetc(void);
10624 static int
10625 preadbuffer(void)
10626 {
10627         char *q;
10628         int more;
10629
10630         if (g_parsefile->strpush) {
10631 #if ENABLE_ASH_ALIAS
10632                 if (g_parsefile->left_in_line == -1
10633                  && g_parsefile->strpush->ap
10634                  && g_parsefile->next_to_pgetc[-1] != ' '
10635                  && g_parsefile->next_to_pgetc[-1] != '\t'
10636                 ) {
10637                         pgetc_debug("preadbuffer PEOA");
10638                         return PEOA;
10639                 }
10640 #endif
10641                 popstring();
10642                 return pgetc();
10643         }
10644         /* on both branches above g_parsefile->left_in_line < 0.
10645          * "pgetc" needs refilling.
10646          */
10647
10648         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10649          * pungetc() may increment it a few times.
10650          * Assuming it won't increment it to less than -90.
10651          */
10652         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10653                 pgetc_debug("preadbuffer PEOF1");
10654                 /* even in failure keep left_in_line and next_to_pgetc
10655                  * in lock step, for correct multi-layer pungetc.
10656                  * left_in_line was decremented before preadbuffer(),
10657                  * must inc next_to_pgetc: */
10658                 g_parsefile->next_to_pgetc++;
10659                 return PEOF;
10660         }
10661
10662         more = g_parsefile->left_in_buffer;
10663         if (more <= 0) {
10664                 flush_stdout_stderr();
10665  again:
10666                 more = preadfd();
10667                 if (more <= 0) {
10668                         /* don't try reading again */
10669                         g_parsefile->left_in_line = -99;
10670                         pgetc_debug("preadbuffer PEOF2");
10671                         g_parsefile->next_to_pgetc++;
10672                         return PEOF;
10673                 }
10674         }
10675
10676         /* Find out where's the end of line.
10677          * Set g_parsefile->left_in_line
10678          * and g_parsefile->left_in_buffer acordingly.
10679          * NUL chars are deleted.
10680          */
10681         q = g_parsefile->next_to_pgetc;
10682         for (;;) {
10683                 char c;
10684
10685                 more--;
10686
10687                 c = *q;
10688                 if (c == '\0') {
10689                         memmove(q, q + 1, more);
10690                 } else {
10691                         q++;
10692                         if (c == '\n') {
10693                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10694                                 break;
10695                         }
10696                 }
10697
10698                 if (more <= 0) {
10699                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10700                         if (g_parsefile->left_in_line < 0)
10701                                 goto again;
10702                         break;
10703                 }
10704         }
10705         g_parsefile->left_in_buffer = more;
10706
10707         if (vflag) {
10708                 char save = *q;
10709                 *q = '\0';
10710                 out2str(g_parsefile->next_to_pgetc);
10711                 *q = save;
10712         }
10713
10714         pgetc_debug("preadbuffer at %d:%p'%s'",
10715                         g_parsefile->left_in_line,
10716                         g_parsefile->next_to_pgetc,
10717                         g_parsefile->next_to_pgetc);
10718         return (unsigned char)*g_parsefile->next_to_pgetc++;
10719 }
10720
10721 static void
10722 nlprompt(void)
10723 {
10724         g_parsefile->linno++;
10725         setprompt_if(doprompt, 2);
10726 }
10727 static void
10728 nlnoprompt(void)
10729 {
10730         g_parsefile->linno++;
10731         needprompt = doprompt;
10732 }
10733
10734 static int
10735 pgetc(void)
10736 {
10737         int c;
10738
10739         pgetc_debug("pgetc at %d:%p'%s'",
10740                         g_parsefile->left_in_line,
10741                         g_parsefile->next_to_pgetc,
10742                         g_parsefile->next_to_pgetc);
10743         if (g_parsefile->unget)
10744                 return g_parsefile->lastc[--g_parsefile->unget];
10745
10746         if (--g_parsefile->left_in_line >= 0)
10747                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10748         else
10749                 c = preadbuffer();
10750
10751         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10752         g_parsefile->lastc[0] = c;
10753
10754         return c;
10755 }
10756
10757 #if ENABLE_ASH_ALIAS
10758 static int
10759 pgetc_without_PEOA(void)
10760 {
10761         int c;
10762         do {
10763                 pgetc_debug("pgetc at %d:%p'%s'",
10764                                 g_parsefile->left_in_line,
10765                                 g_parsefile->next_to_pgetc,
10766                                 g_parsefile->next_to_pgetc);
10767                 c = pgetc();
10768         } while (c == PEOA);
10769         return c;
10770 }
10771 #else
10772 # define pgetc_without_PEOA() pgetc()
10773 #endif
10774
10775 /*
10776  * Undo a call to pgetc.  Only two characters may be pushed back.
10777  * PEOF may be pushed back.
10778  */
10779 static void
10780 pungetc(void)
10781 {
10782         g_parsefile->unget++;
10783 }
10784
10785 /* This one eats backslash+newline */
10786 static int
10787 pgetc_eatbnl(void)
10788 {
10789         int c;
10790
10791         while ((c = pgetc()) == '\\') {
10792                 if (pgetc() != '\n') {
10793                         pungetc();
10794                         break;
10795                 }
10796
10797                 nlprompt();
10798         }
10799
10800         return c;
10801 }
10802
10803 struct synstack {
10804         smalluint syntax;
10805         uint8_t innerdq   :1;
10806         uint8_t varpushed :1;
10807         uint8_t dblquote  :1;
10808         int varnest;            /* levels of variables expansion */
10809         int dqvarnest;          /* levels of variables expansion within double quotes */
10810         int parenlevel;         /* levels of parens in arithmetic */
10811         struct synstack *prev;
10812         struct synstack *next;
10813 };
10814
10815 static void
10816 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10817 {
10818         memset(next, 0, sizeof(*next));
10819         next->syntax = syntax;
10820         next->next = *stack;
10821         (*stack)->prev = next;
10822         *stack = next;
10823 }
10824
10825 static ALWAYS_INLINE void
10826 synstack_pop(struct synstack **stack)
10827 {
10828         *stack = (*stack)->next;
10829 }
10830
10831 /*
10832  * To handle the "." command, a stack of input files is used.  Pushfile
10833  * adds a new entry to the stack and popfile restores the previous level.
10834  */
10835 static void
10836 pushfile(void)
10837 {
10838         struct parsefile *pf;
10839
10840         pf = ckzalloc(sizeof(*pf));
10841         pf->prev = g_parsefile;
10842         pf->pf_fd = -1;
10843         /*pf->strpush = NULL; - ckzalloc did it */
10844         /*pf->basestrpush.prev = NULL;*/
10845         /*pf->unget = 0;*/
10846         g_parsefile = pf;
10847 }
10848
10849 static void
10850 popfile(void)
10851 {
10852         struct parsefile *pf = g_parsefile;
10853
10854         if (pf == &basepf)
10855                 return;
10856
10857         INT_OFF;
10858         if (pf->pf_fd >= 0)
10859                 close(pf->pf_fd);
10860         free(pf->buf);
10861         while (pf->strpush)
10862                 popstring();
10863         g_parsefile = pf->prev;
10864         free(pf);
10865         INT_ON;
10866 }
10867
10868 static void
10869 unwindfiles(struct parsefile *stop)
10870 {
10871         while (g_parsefile != stop)
10872                 popfile();
10873 }
10874
10875 /*
10876  * Return to top level.
10877  */
10878 static void
10879 popallfiles(void)
10880 {
10881         unwindfiles(&basepf);
10882 }
10883
10884 /*
10885  * Close the file(s) that the shell is reading commands from.  Called
10886  * after a fork is done.
10887  */
10888 static void
10889 closescript(void)
10890 {
10891         popallfiles();
10892         if (g_parsefile->pf_fd > 0) {
10893                 close(g_parsefile->pf_fd);
10894                 g_parsefile->pf_fd = 0;
10895         }
10896 }
10897
10898 /*
10899  * Like setinputfile, but takes an open file descriptor.  Call this with
10900  * interrupts off.
10901  */
10902 static void
10903 setinputfd(int fd, int push)
10904 {
10905         if (push) {
10906                 pushfile();
10907                 g_parsefile->buf = NULL;
10908         }
10909         g_parsefile->pf_fd = fd;
10910         if (g_parsefile->buf == NULL)
10911                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10912         g_parsefile->left_in_buffer = 0;
10913         g_parsefile->left_in_line = 0;
10914         g_parsefile->linno = 1;
10915 }
10916
10917 /*
10918  * Set the input to take input from a file.  If push is set, push the
10919  * old input onto the stack first.
10920  */
10921 static int
10922 setinputfile(const char *fname, int flags)
10923 {
10924         int fd;
10925
10926         INT_OFF;
10927         fd = open(fname, O_RDONLY | O_CLOEXEC);
10928         if (fd < 0) {
10929                 if (flags & INPUT_NOFILE_OK)
10930                         goto out;
10931                 exitstatus = 127;
10932                 ash_msg_and_raise_perror("can't open '%s'", fname);
10933         }
10934         if (fd < 10)
10935                 fd = savefd(fd);
10936         else if (O_CLOEXEC == 0) /* old libc */
10937                 close_on_exec_on(fd);
10938
10939         setinputfd(fd, flags & INPUT_PUSH_FILE);
10940  out:
10941         INT_ON;
10942         return fd;
10943 }
10944
10945 /*
10946  * Like setinputfile, but takes input from a string.
10947  */
10948 static void
10949 setinputstring(char *string)
10950 {
10951         INT_OFF;
10952         pushfile();
10953         g_parsefile->next_to_pgetc = string;
10954         g_parsefile->left_in_line = strlen(string);
10955         g_parsefile->buf = NULL;
10956         g_parsefile->linno = 1;
10957         INT_ON;
10958 }
10959
10960
10961 /*
10962  * Routines to check for mail.
10963  */
10964
10965 #if ENABLE_ASH_MAIL
10966
10967 /* Hash of mtimes of mailboxes */
10968 static unsigned mailtime_hash;
10969 /* Set if MAIL or MAILPATH is changed. */
10970 static smallint mail_var_path_changed;
10971
10972 /*
10973  * Print appropriate message(s) if mail has arrived.
10974  * If mail_var_path_changed is set,
10975  * then the value of MAIL has mail_var_path_changed,
10976  * so we just update the values.
10977  */
10978 static void
10979 chkmail(void)
10980 {
10981         const char *mpath;
10982         char *p;
10983         char *q;
10984         unsigned new_hash;
10985         struct stackmark smark;
10986         struct stat statb;
10987
10988         setstackmark(&smark);
10989         mpath = mpathset() ? mpathval() : mailval();
10990         new_hash = 0;
10991         for (;;) {
10992                 p = path_advance(&mpath, nullstr);
10993                 if (p == NULL)
10994                         break;
10995                 if (*p == '\0')
10996                         continue;
10997                 for (q = p; *q; q++)
10998                         continue;
10999 #if DEBUG
11000                 if (q[-1] != '/')
11001                         abort();
11002 #endif
11003                 q[-1] = '\0';                   /* delete trailing '/' */
11004                 if (stat(p, &statb) < 0) {
11005                         continue;
11006                 }
11007                 /* Very simplistic "hash": just a sum of all mtimes */
11008                 new_hash += (unsigned)statb.st_mtime;
11009         }
11010         if (!mail_var_path_changed && mailtime_hash != new_hash) {
11011                 if (mailtime_hash != 0)
11012                         out2str("you have mail\n");
11013                 mailtime_hash = new_hash;
11014         }
11015         mail_var_path_changed = 0;
11016         popstackmark(&smark);
11017 }
11018
11019 static void FAST_FUNC
11020 changemail(const char *val UNUSED_PARAM)
11021 {
11022         mail_var_path_changed = 1;
11023 }
11024
11025 #endif /* ASH_MAIL */
11026
11027
11028 /* ============ ??? */
11029
11030 /*
11031  * Set the shell parameters.
11032  */
11033 static void
11034 setparam(char **argv)
11035 {
11036         char **newparam;
11037         char **ap;
11038         int nparam;
11039
11040         for (nparam = 0; argv[nparam]; nparam++)
11041                 continue;
11042         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11043         while (*argv) {
11044                 *ap++ = ckstrdup(*argv++);
11045         }
11046         *ap = NULL;
11047         freeparam(&shellparam);
11048         shellparam.malloced = 1;
11049         shellparam.nparam = nparam;
11050         shellparam.p = newparam;
11051 #if ENABLE_ASH_GETOPTS
11052         shellparam.optind = 1;
11053         shellparam.optoff = -1;
11054 #endif
11055 }
11056
11057 /*
11058  * Process shell options.  The global variable argptr contains a pointer
11059  * to the argument list; we advance it past the options.
11060  *
11061  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11062  * For a non-interactive shell, an error condition encountered
11063  * by a special built-in ... shall cause the shell to write a diagnostic message
11064  * to standard error and exit as shown in the following table:
11065  * Error                                           Special Built-In
11066  * ...
11067  * Utility syntax error (option or operand error)  Shall exit
11068  * ...
11069  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11070  * we see that bash does not do that (set "finishes" with error code 1 instead,
11071  * and shell continues), and people rely on this behavior!
11072  * Testcase:
11073  * set -o barfoo 2>/dev/null
11074  * echo $?
11075  *
11076  * Oh well. Let's mimic that.
11077  */
11078 static int
11079 plus_minus_o(char *name, int val)
11080 {
11081         int i;
11082
11083         if (name) {
11084                 for (i = 0; i < NOPTS; i++) {
11085                         if (strcmp(name, optnames(i)) == 0) {
11086                                 optlist[i] = val;
11087                                 return 0;
11088                         }
11089                 }
11090                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
11091                 return 1;
11092         }
11093         for (i = 0; i < NOPTS; i++) {
11094                 if (optnames(i)[0] == '\0')
11095                         continue;
11096                 if (val) {
11097                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11098                 } else {
11099                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11100                 }
11101         }
11102         return 0;
11103 }
11104 static void
11105 setoption(int flag, int val)
11106 {
11107         int i;
11108
11109         for (i = 0; i < NOPTS; i++) {
11110                 if (optletters(i) == flag && optnames(i)[0] != '\0') {
11111                         optlist[i] = val;
11112                         return;
11113                 }
11114         }
11115         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11116         /* NOTREACHED */
11117 }
11118 /* If login_sh is not NULL, we are called to parse command line opts,
11119  * not "set -opts"
11120  */
11121 static int
11122 options(int *login_sh)
11123 {
11124         char *p;
11125         int val;
11126         int c;
11127
11128         if (login_sh)
11129                 minusc = NULL;
11130         while ((p = *argptr) != NULL) {
11131                 c = *p++;
11132                 if (c != '-' && c != '+')
11133                         break;
11134                 argptr++;
11135                 val = 0; /* val = 0 if c == '+' */
11136                 if (c == '-') {
11137                         val = 1;
11138                         if (p[0] == '\0' || LONE_DASH(p)) {
11139                                 if (!login_sh) {
11140                                         /* "-" means turn off -x and -v */
11141                                         if (p[0] == '\0')
11142                                                 xflag = vflag = 0;
11143                                         /* "--" means reset params */
11144                                         else if (*argptr == NULL)
11145                                                 setparam(argptr);
11146                                 }
11147                                 break;    /* "-" or "--" terminates options */
11148                         }
11149                 }
11150                 /* first char was + or - */
11151                 while ((c = *p++) != '\0') {
11152                         if (login_sh) {
11153                                 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11154                                 if (c == 'c') {
11155                                         minusc = p; /* command is after shell args */
11156                                         cflag = 1;
11157                                         continue;
11158                                 }
11159                                 if (c == 's') { /* -s, +s */
11160                                         sflag = 1;
11161                                         continue;
11162                                 }
11163                                 if (c == 'i') { /* -i, +i */
11164                                         iflag = 1;
11165                                         continue;
11166                                 }
11167                                 if (c == 'l') {
11168                                         *login_sh = 1; /* -l or +l == --login */
11169                                         continue;
11170                                 }
11171                                 /* bash does not accept +-login, we also won't */
11172                                 if (val && (c == '-')) { /* long options */
11173                                         if (strcmp(p, "login") == 0) {
11174                                                 *login_sh = 1;
11175                                         }
11176                                         break;
11177                                 }
11178                         }
11179                         if (c == 'o') {
11180                                 if (plus_minus_o(*argptr, val)) {
11181                                         /* it already printed err message */
11182                                         return 1; /* error */
11183                                 }
11184                                 if (*argptr)
11185                                         argptr++;
11186                         } else {
11187                                 setoption(c, val);
11188                         }
11189                 }
11190         }
11191         return 0;
11192 }
11193
11194 /*
11195  * The shift builtin command.
11196  */
11197 static int FAST_FUNC
11198 shiftcmd(int argc UNUSED_PARAM, char **argv)
11199 {
11200         int n;
11201         char **ap1, **ap2;
11202
11203         n = 1;
11204         if (argv[1])
11205                 n = number(argv[1]);
11206         if (n > shellparam.nparam)
11207                 return 1;
11208         INT_OFF;
11209         shellparam.nparam -= n;
11210         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11211                 if (shellparam.malloced)
11212                         free(*ap1);
11213         }
11214         ap2 = shellparam.p;
11215         while ((*ap2++ = *ap1++) != NULL)
11216                 continue;
11217 #if ENABLE_ASH_GETOPTS
11218         shellparam.optind = 1;
11219         shellparam.optoff = -1;
11220 #endif
11221         INT_ON;
11222         return 0;
11223 }
11224
11225 /*
11226  * POSIX requires that 'set' (but not export or readonly) output the
11227  * variables in lexicographic order - by the locale's collating order (sigh).
11228  * Maybe we could keep them in an ordered balanced binary tree
11229  * instead of hashed lists.
11230  * For now just roll 'em through qsort for printing...
11231  */
11232 static int
11233 showvars(const char *sep_prefix, int on, int off)
11234 {
11235         const char *sep;
11236         char **ep, **epend;
11237
11238         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11239         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11240
11241         sep = *sep_prefix ? " " : sep_prefix;
11242
11243         for (; ep < epend; ep++) {
11244                 const char *p;
11245                 const char *q;
11246
11247                 p = endofname(*ep);
11248 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11249  * makes "export -p" to have output not suitable for "eval":
11250  * import os
11251  * os.environ["test-test"]="test"
11252  * if os.fork() == 0:
11253  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11254  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11255  */
11256                 q = nullstr;
11257                 if (*p == '=')
11258                         q = single_quote(++p);
11259                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11260         }
11261         return 0;
11262 }
11263
11264 /*
11265  * The set command builtin.
11266  */
11267 static int FAST_FUNC
11268 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11269 {
11270         int retval;
11271
11272         if (!argv[1])
11273                 return showvars(nullstr, 0, VUNSET);
11274
11275         INT_OFF;
11276         retval = options(/*login_sh:*/ NULL);
11277         if (retval == 0) { /* if no parse error... */
11278                 optschanged();
11279                 if (*argptr != NULL) {
11280                         setparam(argptr);
11281                 }
11282         }
11283         INT_ON;
11284         return retval;
11285 }
11286
11287 #if ENABLE_ASH_RANDOM_SUPPORT
11288 static void FAST_FUNC
11289 change_random(const char *value)
11290 {
11291         uint32_t t;
11292
11293         if (value == NULL) {
11294                 /* "get", generate */
11295                 t = next_random(&random_gen);
11296                 /* set without recursion */
11297                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11298                 vrandom.flags &= ~VNOFUNC;
11299         } else {
11300                 /* set/reset */
11301                 t = strtoul(value, NULL, 10);
11302                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11303         }
11304 }
11305 #endif
11306
11307 #if BASH_EPOCH_VARS
11308 static void FAST_FUNC
11309 change_epoch(struct var *vepoch, const char *fmt)
11310 {
11311         struct timeval tv;
11312         char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3];
11313
11314         gettimeofday(&tv, NULL);
11315         sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec);
11316         setvar(vepoch->var_text, buffer, VNOFUNC);
11317         vepoch->flags &= ~VNOFUNC;
11318 }
11319
11320 static void FAST_FUNC
11321 change_seconds(const char *value UNUSED_PARAM)
11322 {
11323         change_epoch(&vepochs, "%lu");
11324 }
11325
11326 static void FAST_FUNC
11327 change_realtime(const char *value UNUSED_PARAM)
11328 {
11329         change_epoch(&vepochr, "%lu.%06u");
11330 }
11331 #endif
11332
11333 #if ENABLE_ASH_GETOPTS
11334 static int
11335 getopts(char *optstr, char *optvar, char **optfirst)
11336 {
11337         char *p, *q;
11338         char c = '?';
11339         int done = 0;
11340         char sbuf[2];
11341         char **optnext;
11342         int ind = shellparam.optind;
11343         int off = shellparam.optoff;
11344
11345         sbuf[1] = '\0';
11346
11347         shellparam.optind = -1;
11348         optnext = optfirst + ind - 1;
11349
11350         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11351                 p = NULL;
11352         else
11353                 p = optnext[-1] + off;
11354         if (p == NULL || *p == '\0') {
11355                 /* Current word is done, advance */
11356                 p = *optnext;
11357                 if (p == NULL || *p != '-' || *++p == '\0') {
11358  atend:
11359                         unsetvar("OPTARG");
11360                         p = NULL;
11361                         done = 1;
11362                         goto out;
11363                 }
11364                 optnext++;
11365                 if (LONE_DASH(p))        /* check for "--" */
11366                         goto atend;
11367         }
11368
11369         c = *p++;
11370         for (q = optstr; *q != c;) {
11371                 if (*q == '\0') {
11372                         /* OPTERR is a bashism */
11373                         const char *cp = lookupvar("OPTERR");
11374                         if ((cp && LONE_CHAR(cp, '0'))
11375                          || (optstr[0] == ':')
11376                         ) {
11377                                 sbuf[0] = c;
11378                                 /*sbuf[1] = '\0'; - already is */
11379                                 setvar0("OPTARG", sbuf);
11380                         } else {
11381                                 fprintf(stderr, "Illegal option -%c\n", c);
11382                                 unsetvar("OPTARG");
11383                         }
11384                         c = '?';
11385                         goto out;
11386                 }
11387                 if (*++q == ':')
11388                         q++;
11389         }
11390
11391         if (*++q == ':') {
11392                 if (*p == '\0' && (p = *optnext) == NULL) {
11393                         /* OPTERR is a bashism */
11394                         const char *cp = lookupvar("OPTERR");
11395                         if ((cp && LONE_CHAR(cp, '0'))
11396                          || (optstr[0] == ':')
11397                         ) {
11398                                 sbuf[0] = c;
11399                                 /*sbuf[1] = '\0'; - already is */
11400                                 setvar0("OPTARG", sbuf);
11401                                 c = ':';
11402                         } else {
11403                                 fprintf(stderr, "No arg for -%c option\n", c);
11404                                 unsetvar("OPTARG");
11405                                 c = '?';
11406                         }
11407                         goto out;
11408                 }
11409
11410                 if (p == *optnext)
11411                         optnext++;
11412                 setvar0("OPTARG", p);
11413                 p = NULL;
11414         } else
11415                 setvar0("OPTARG", nullstr);
11416  out:
11417         ind = optnext - optfirst + 1;
11418         setvar("OPTIND", itoa(ind), VNOFUNC);
11419         sbuf[0] = c;
11420         /*sbuf[1] = '\0'; - already is */
11421         setvar0(optvar, sbuf);
11422
11423         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11424         shellparam.optind = ind;
11425
11426         return done;
11427 }
11428
11429 /*
11430  * The getopts builtin.  Shellparam.optnext points to the next argument
11431  * to be processed.  Shellparam.optptr points to the next character to
11432  * be processed in the current argument.  If shellparam.optnext is NULL,
11433  * then it's the first time getopts has been called.
11434  */
11435 static int FAST_FUNC
11436 getoptscmd(int argc, char **argv)
11437 {
11438         char **optbase;
11439
11440         if (argc < 3)
11441                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11442         if (argc == 3) {
11443                 optbase = shellparam.p;
11444                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11445                         shellparam.optind = 1;
11446                         shellparam.optoff = -1;
11447                 }
11448         } else {
11449                 optbase = &argv[3];
11450                 if ((unsigned)shellparam.optind > argc - 2) {
11451                         shellparam.optind = 1;
11452                         shellparam.optoff = -1;
11453                 }
11454         }
11455
11456         return getopts(argv[1], argv[2], optbase);
11457 }
11458 #endif /* ASH_GETOPTS */
11459
11460
11461 /* ============ Shell parser */
11462
11463 struct heredoc {
11464         struct heredoc *next;   /* next here document in list */
11465         union node *here;       /* redirection node */
11466         char *eofmark;          /* string indicating end of input */
11467         smallint striptabs;     /* if set, strip leading tabs */
11468 };
11469
11470 static smallint tokpushback;           /* last token pushed back */
11471 static smallint quoteflag;             /* set if (part of) last token was quoted */
11472 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11473 static struct heredoc *heredoclist;    /* list of here documents to read */
11474 static char *wordtext;                 /* text of last word returned by readtoken */
11475 static struct nodelist *backquotelist;
11476 static union node *redirnode;
11477 static struct heredoc *heredoc;
11478
11479 static const char *
11480 tokname(char *buf, int tok)
11481 {
11482         if (tok < TSEMI)
11483                 return tokname_array[tok];
11484         sprintf(buf, "\"%s\"", tokname_array[tok]);
11485         return buf;
11486 }
11487
11488 /* raise_error_unexpected_syntax:
11489  * Called when an unexpected token is read during the parse.  The argument
11490  * is the token that is expected, or -1 if more than one type of token can
11491  * occur at this point.
11492  */
11493 static void raise_error_unexpected_syntax(int) NORETURN;
11494 static void
11495 raise_error_unexpected_syntax(int token)
11496 {
11497         char msg[64];
11498         char buf[16];
11499         int l;
11500
11501         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11502         if (token >= 0)
11503                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11504         raise_error_syntax(msg);
11505         /* NOTREACHED */
11506 }
11507
11508 /* parsing is heavily cross-recursive, need these forward decls */
11509 static union node *andor(void);
11510 static union node *pipeline(void);
11511 static union node *parse_command(void);
11512 static void parseheredoc(void);
11513 static int peektoken(void);
11514 static int readtoken(void);
11515
11516 static union node *
11517 list(int nlflag)
11518 {
11519         union node *n1, *n2, *n3;
11520         int tok;
11521
11522         n1 = NULL;
11523         for (;;) {
11524                 switch (peektoken()) {
11525                 case TNL:
11526                         if (!(nlflag & 1))
11527                                 break;
11528                         parseheredoc();
11529                         return n1;
11530
11531                 case TEOF:
11532                         if (!n1 && (nlflag & 1))
11533                                 n1 = NODE_EOF;
11534                         parseheredoc();
11535                         return n1;
11536                 }
11537
11538                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11539                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11540                         return n1;
11541                 nlflag |= 2;
11542
11543                 n2 = andor();
11544                 tok = readtoken();
11545                 if (tok == TBACKGND) {
11546                         if (n2->type == NPIPE) {
11547                                 n2->npipe.pipe_backgnd = 1;
11548                         } else {
11549                                 if (n2->type != NREDIR) {
11550                                         n3 = stzalloc(sizeof(struct nredir));
11551                                         n3->nredir.n = n2;
11552                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11553                                         n2 = n3;
11554                                 }
11555                                 n2->type = NBACKGND;
11556                         }
11557                 }
11558                 if (n1 == NULL) {
11559                         n1 = n2;
11560                 } else {
11561                         n3 = stzalloc(sizeof(struct nbinary));
11562                         n3->type = NSEMI;
11563                         n3->nbinary.ch1 = n1;
11564                         n3->nbinary.ch2 = n2;
11565                         n1 = n3;
11566                 }
11567                 switch (tok) {
11568                 case TNL:
11569                 case TEOF:
11570                         tokpushback = 1;
11571                         /* fall through */
11572                 case TBACKGND:
11573                 case TSEMI:
11574                         break;
11575                 default:
11576                         if ((nlflag & 1))
11577                                 raise_error_unexpected_syntax(-1);
11578                         tokpushback = 1;
11579                         return n1;
11580                 }
11581         }
11582 }
11583
11584 static union node *
11585 andor(void)
11586 {
11587         union node *n1, *n2, *n3;
11588         int t;
11589
11590         n1 = pipeline();
11591         for (;;) {
11592                 t = readtoken();
11593                 if (t == TAND) {
11594                         t = NAND;
11595                 } else if (t == TOR) {
11596                         t = NOR;
11597                 } else {
11598                         tokpushback = 1;
11599                         return n1;
11600                 }
11601                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11602                 n2 = pipeline();
11603                 n3 = stzalloc(sizeof(struct nbinary));
11604                 n3->type = t;
11605                 n3->nbinary.ch1 = n1;
11606                 n3->nbinary.ch2 = n2;
11607                 n1 = n3;
11608         }
11609 }
11610
11611 static union node *
11612 pipeline(void)
11613 {
11614         union node *n1, *n2, *pipenode;
11615         struct nodelist *lp, *prev;
11616         int negate;
11617
11618         negate = 0;
11619         TRACE(("pipeline: entered\n"));
11620         if (readtoken() == TNOT) {
11621                 negate = !negate;
11622                 checkkwd = CHKKWD | CHKALIAS;
11623         } else
11624                 tokpushback = 1;
11625         n1 = parse_command();
11626         if (readtoken() == TPIPE) {
11627                 pipenode = stzalloc(sizeof(struct npipe));
11628                 pipenode->type = NPIPE;
11629                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11630                 lp = stzalloc(sizeof(struct nodelist));
11631                 pipenode->npipe.cmdlist = lp;
11632                 lp->n = n1;
11633                 do {
11634                         prev = lp;
11635                         lp = stzalloc(sizeof(struct nodelist));
11636                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11637                         lp->n = parse_command();
11638                         prev->next = lp;
11639                 } while (readtoken() == TPIPE);
11640                 lp->next = NULL;
11641                 n1 = pipenode;
11642         }
11643         tokpushback = 1;
11644         if (negate) {
11645                 n2 = stzalloc(sizeof(struct nnot));
11646                 n2->type = NNOT;
11647                 n2->nnot.com = n1;
11648                 return n2;
11649         }
11650         return n1;
11651 }
11652
11653 static union node *
11654 makename(void)
11655 {
11656         union node *n;
11657
11658         n = stzalloc(sizeof(struct narg));
11659         n->type = NARG;
11660         /*n->narg.next = NULL; - stzalloc did it */
11661         n->narg.text = wordtext;
11662         n->narg.backquote = backquotelist;
11663         return n;
11664 }
11665
11666 static void
11667 fixredir(union node *n, const char *text, int err)
11668 {
11669         int fd;
11670
11671         TRACE(("Fix redir %s %d\n", text, err));
11672         if (!err)
11673                 n->ndup.vname = NULL;
11674
11675         fd = bb_strtou(text, NULL, 10);
11676         if (!errno && fd >= 0)
11677                 n->ndup.dupfd = fd;
11678         else if (LONE_DASH(text))
11679                 n->ndup.dupfd = -1;
11680         else {
11681                 if (err)
11682                         raise_error_syntax("bad fd number");
11683                 n->ndup.vname = makename();
11684         }
11685 }
11686
11687 static void
11688 parsefname(void)
11689 {
11690         union node *n = redirnode;
11691
11692         if (n->type == NHERE)
11693                 checkkwd = CHKEOFMARK;
11694         if (readtoken() != TWORD)
11695                 raise_error_unexpected_syntax(-1);
11696         if (n->type == NHERE) {
11697                 struct heredoc *here = heredoc;
11698                 struct heredoc *p;
11699
11700                 if (quoteflag == 0)
11701                         n->type = NXHERE;
11702                 TRACE(("Here document %d\n", n->type));
11703                 rmescapes(wordtext, 0, NULL);
11704                 here->eofmark = wordtext;
11705                 here->next = NULL;
11706                 if (heredoclist == NULL)
11707                         heredoclist = here;
11708                 else {
11709                         for (p = heredoclist; p->next; p = p->next)
11710                                 continue;
11711                         p->next = here;
11712                 }
11713         } else if (n->type == NTOFD || n->type == NFROMFD) {
11714                 fixredir(n, wordtext, 0);
11715         } else {
11716                 n->nfile.fname = makename();
11717         }
11718 }
11719
11720 static union node *
11721 simplecmd(void)
11722 {
11723         union node *args, **app;
11724         union node *n = NULL;
11725         union node *vars, **vpp;
11726         union node **rpp, *redir;
11727         int savecheckkwd;
11728         int savelinno;
11729 #if BASH_TEST2
11730         smallint double_brackets_flag = 0;
11731 #endif
11732         IF_BASH_FUNCTION(smallint function_flag = 0;)
11733
11734         args = NULL;
11735         app = &args;
11736         vars = NULL;
11737         vpp = &vars;
11738         redir = NULL;
11739         rpp = &redir;
11740
11741         savecheckkwd = CHKALIAS;
11742         savelinno = g_parsefile->linno;
11743         for (;;) {
11744                 int t;
11745                 checkkwd = savecheckkwd;
11746                 t = readtoken();
11747                 switch (t) {
11748 #if BASH_FUNCTION
11749                 case TFUNCTION:
11750                         if (peektoken() != TWORD)
11751                                 raise_error_unexpected_syntax(TWORD);
11752                         function_flag = 1;
11753                         break;
11754 #endif
11755 #if BASH_TEST2
11756                 case TAND: /* "&&" */
11757                 case TOR: /* "||" */
11758                         if (!double_brackets_flag) {
11759                                 tokpushback = 1;
11760                                 goto out;
11761                         }
11762                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11763 #endif
11764                 case TWORD:
11765                         n = stzalloc(sizeof(struct narg));
11766                         n->type = NARG;
11767                         /*n->narg.next = NULL; - stzalloc did it */
11768                         n->narg.text = wordtext;
11769 #if BASH_TEST2
11770                         if (strcmp("[[", wordtext) == 0)
11771                                 double_brackets_flag = 1;
11772                         else if (strcmp("]]", wordtext) == 0)
11773                                 double_brackets_flag = 0;
11774 #endif
11775                         n->narg.backquote = backquotelist;
11776                         if (savecheckkwd && isassignment(wordtext)) {
11777                                 *vpp = n;
11778                                 vpp = &n->narg.next;
11779                         } else {
11780                                 *app = n;
11781                                 app = &n->narg.next;
11782                                 savecheckkwd = 0;
11783                         }
11784 #if BASH_FUNCTION
11785                         if (function_flag) {
11786                                 checkkwd = CHKNL | CHKKWD;
11787                                 switch (peektoken()) {
11788                                 case TBEGIN:
11789                                 case TIF:
11790                                 case TCASE:
11791                                 case TUNTIL:
11792                                 case TWHILE:
11793                                 case TFOR:
11794                                         goto do_func;
11795                                 case TLP:
11796                                         function_flag = 0;
11797                                         break;
11798 # if BASH_TEST2
11799                                 case TWORD:
11800                                         if (strcmp("[[", wordtext) == 0)
11801                                                 goto do_func;
11802                                         /* fall through */
11803 # endif
11804                                 default:
11805                                         raise_error_unexpected_syntax(-1);
11806                                 }
11807                         }
11808 #endif
11809                         break;
11810                 case TREDIR:
11811                         *rpp = n = redirnode;
11812                         rpp = &n->nfile.next;
11813                         parsefname();   /* read name of redirection file */
11814                         break;
11815                 case TLP:
11816  IF_BASH_FUNCTION(do_func:)
11817                         if (args && app == &args->narg.next
11818                          && !vars && !redir
11819                         ) {
11820                                 struct builtincmd *bcmd;
11821                                 const char *name;
11822
11823                                 /* We have a function */
11824                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11825                                         raise_error_unexpected_syntax(TRP);
11826                                 name = n->narg.text;
11827                                 if (!goodname(name)
11828                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11829                                 ) {
11830                                         raise_error_syntax("bad function name");
11831                                 }
11832                                 n->type = NDEFUN;
11833                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11834                                 n->ndefun.text = n->narg.text;
11835                                 n->ndefun.linno = g_parsefile->linno;
11836                                 n->ndefun.body = parse_command();
11837                                 return n;
11838                         }
11839                         IF_BASH_FUNCTION(function_flag = 0;)
11840                         /* fall through */
11841                 default:
11842                         tokpushback = 1;
11843                         goto out;
11844                 }
11845         }
11846  out:
11847         *app = NULL;
11848         *vpp = NULL;
11849         *rpp = NULL;
11850         n = stzalloc(sizeof(struct ncmd));
11851         if (NCMD != 0)
11852                 n->type = NCMD;
11853         n->ncmd.linno = savelinno;
11854         n->ncmd.args = args;
11855         n->ncmd.assign = vars;
11856         n->ncmd.redirect = redir;
11857         return n;
11858 }
11859
11860 static union node *
11861 parse_command(void)
11862 {
11863         union node *n1, *n2;
11864         union node *ap, **app;
11865         union node *cp, **cpp;
11866         union node *redir, **rpp;
11867         union node **rpp2;
11868         int t;
11869         int savelinno;
11870
11871         redir = NULL;
11872         rpp2 = &redir;
11873
11874         savelinno = g_parsefile->linno;
11875
11876         switch (readtoken()) {
11877         default:
11878                 raise_error_unexpected_syntax(-1);
11879                 /* NOTREACHED */
11880         case TIF:
11881                 n1 = stzalloc(sizeof(struct nif));
11882                 n1->type = NIF;
11883                 n1->nif.test = list(0);
11884                 if (readtoken() != TTHEN)
11885                         raise_error_unexpected_syntax(TTHEN);
11886                 n1->nif.ifpart = list(0);
11887                 n2 = n1;
11888                 while (readtoken() == TELIF) {
11889                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11890                         n2 = n2->nif.elsepart;
11891                         n2->type = NIF;
11892                         n2->nif.test = list(0);
11893                         if (readtoken() != TTHEN)
11894                                 raise_error_unexpected_syntax(TTHEN);
11895                         n2->nif.ifpart = list(0);
11896                 }
11897                 if (lasttoken == TELSE)
11898                         n2->nif.elsepart = list(0);
11899                 else {
11900                         n2->nif.elsepart = NULL;
11901                         tokpushback = 1;
11902                 }
11903                 t = TFI;
11904                 break;
11905         case TWHILE:
11906         case TUNTIL: {
11907                 int got;
11908                 n1 = stzalloc(sizeof(struct nbinary));
11909                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11910                 n1->nbinary.ch1 = list(0);
11911                 got = readtoken();
11912                 if (got != TDO) {
11913                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11914                                         got == TWORD ? wordtext : ""));
11915                         raise_error_unexpected_syntax(TDO);
11916                 }
11917                 n1->nbinary.ch2 = list(0);
11918                 t = TDONE;
11919                 break;
11920         }
11921         case TFOR:
11922                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11923                         raise_error_syntax("bad for loop variable");
11924                 n1 = stzalloc(sizeof(struct nfor));
11925                 n1->type = NFOR;
11926                 n1->nfor.linno = savelinno;
11927                 n1->nfor.var = wordtext;
11928                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11929                 if (readtoken() == TIN) {
11930                         app = &ap;
11931                         while (readtoken() == TWORD) {
11932                                 n2 = stzalloc(sizeof(struct narg));
11933                                 n2->type = NARG;
11934                                 /*n2->narg.next = NULL; - stzalloc did it */
11935                                 n2->narg.text = wordtext;
11936                                 n2->narg.backquote = backquotelist;
11937                                 *app = n2;
11938                                 app = &n2->narg.next;
11939                         }
11940                         *app = NULL;
11941                         n1->nfor.args = ap;
11942                         if (lasttoken != TNL && lasttoken != TSEMI)
11943                                 raise_error_unexpected_syntax(-1);
11944                 } else {
11945                         n2 = stzalloc(sizeof(struct narg));
11946                         n2->type = NARG;
11947                         /*n2->narg.next = NULL; - stzalloc did it */
11948                         n2->narg.text = (char *)dolatstr;
11949                         /*n2->narg.backquote = NULL;*/
11950                         n1->nfor.args = n2;
11951                         /*
11952                          * Newline or semicolon here is optional (but note
11953                          * that the original Bourne shell only allowed NL).
11954                          */
11955                         if (lasttoken != TSEMI)
11956                                 tokpushback = 1;
11957                 }
11958                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11959                 if (readtoken() != TDO)
11960                         raise_error_unexpected_syntax(TDO);
11961                 n1->nfor.body = list(0);
11962                 t = TDONE;
11963                 break;
11964         case TCASE:
11965                 n1 = stzalloc(sizeof(struct ncase));
11966                 n1->type = NCASE;
11967                 n1->ncase.linno = savelinno;
11968                 if (readtoken() != TWORD)
11969                         raise_error_unexpected_syntax(TWORD);
11970                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11971                 n2->type = NARG;
11972                 /*n2->narg.next = NULL; - stzalloc did it */
11973                 n2->narg.text = wordtext;
11974                 n2->narg.backquote = backquotelist;
11975                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11976                 if (readtoken() != TIN)
11977                         raise_error_unexpected_syntax(TIN);
11978                 cpp = &n1->ncase.cases;
11979  next_case:
11980                 checkkwd = CHKNL | CHKKWD;
11981                 t = readtoken();
11982                 while (t != TESAC) {
11983                         if (lasttoken == TLP)
11984                                 readtoken();
11985                         *cpp = cp = stzalloc(sizeof(struct nclist));
11986                         cp->type = NCLIST;
11987                         app = &cp->nclist.pattern;
11988                         for (;;) {
11989                                 *app = ap = stzalloc(sizeof(struct narg));
11990                                 ap->type = NARG;
11991                                 /*ap->narg.next = NULL; - stzalloc did it */
11992                                 ap->narg.text = wordtext;
11993                                 ap->narg.backquote = backquotelist;
11994                                 if (readtoken() != TPIPE)
11995                                         break;
11996                                 app = &ap->narg.next;
11997                                 readtoken();
11998                         }
11999                         //ap->narg.next = NULL;
12000                         if (lasttoken != TRP)
12001                                 raise_error_unexpected_syntax(TRP);
12002                         cp->nclist.body = list(2);
12003
12004                         cpp = &cp->nclist.next;
12005
12006                         checkkwd = CHKNL | CHKKWD;
12007                         t = readtoken();
12008                         if (t != TESAC) {
12009                                 if (t != TENDCASE)
12010                                         raise_error_unexpected_syntax(TENDCASE);
12011                                 goto next_case;
12012                         }
12013                 }
12014                 *cpp = NULL;
12015                 goto redir;
12016         case TLP:
12017                 n1 = stzalloc(sizeof(struct nredir));
12018                 n1->type = NSUBSHELL;
12019                 n1->nredir.linno = savelinno;
12020                 n1->nredir.n = list(0);
12021                 /*n1->nredir.redirect = NULL; - stzalloc did it */
12022                 t = TRP;
12023                 break;
12024         case TBEGIN:
12025                 n1 = list(0);
12026                 t = TEND;
12027                 break;
12028         IF_BASH_FUNCTION(case TFUNCTION:)
12029         case TWORD:
12030         case TREDIR:
12031                 tokpushback = 1;
12032                 return simplecmd();
12033         }
12034
12035         if (readtoken() != t)
12036                 raise_error_unexpected_syntax(t);
12037
12038  redir:
12039         /* Now check for redirection which may follow command */
12040         checkkwd = CHKKWD | CHKALIAS;
12041         rpp = rpp2;
12042         while (readtoken() == TREDIR) {
12043                 *rpp = n2 = redirnode;
12044                 rpp = &n2->nfile.next;
12045                 parsefname();
12046         }
12047         tokpushback = 1;
12048         *rpp = NULL;
12049         if (redir) {
12050                 if (n1->type != NSUBSHELL) {
12051                         n2 = stzalloc(sizeof(struct nredir));
12052                         n2->type = NREDIR;
12053                         n2->nredir.linno = savelinno;
12054                         n2->nredir.n = n1;
12055                         n1 = n2;
12056                 }
12057                 n1->nredir.redirect = redir;
12058         }
12059         return n1;
12060 }
12061
12062 #if BASH_DOLLAR_SQUOTE
12063 static int
12064 decode_dollar_squote(void)
12065 {
12066         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12067         int c, cnt;
12068         char *p;
12069         char buf[4];
12070
12071         c = pgetc();
12072         p = strchr(C_escapes, c);
12073         if (p) {
12074                 buf[0] = c;
12075                 p = buf;
12076                 cnt = 3;
12077                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12078                         do {
12079                                 c = pgetc();
12080                                 *++p = c;
12081                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
12082                         pungetc();
12083                 } else if (c == 'x') { /* \xHH */
12084                         do {
12085                                 c = pgetc();
12086                                 *++p = c;
12087                         } while (isxdigit(c) && --cnt);
12088                         pungetc();
12089                         if (cnt == 3) { /* \x but next char is "bad" */
12090                                 c = 'x';
12091                                 goto unrecognized;
12092                         }
12093                 } else { /* simple seq like \\ or \t */
12094                         p++;
12095                 }
12096                 *p = '\0';
12097                 p = buf;
12098                 c = bb_process_escape_sequence((void*)&p);
12099         } else { /* unrecognized "\z": print both chars unless ' or " */
12100                 if (c != '\'' && c != '"') {
12101  unrecognized:
12102                         c |= 0x100; /* "please encode \, then me" */
12103                 }
12104         }
12105         return c;
12106 }
12107 #endif
12108
12109 /* Used by expandstr to get here-doc like behaviour. */
12110 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12111
12112 static ALWAYS_INLINE int
12113 realeofmark(const char *eofmark)
12114 {
12115         return eofmark && eofmark != FAKEEOFMARK;
12116 }
12117
12118 /*
12119  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12120  * is not NULL, read a here document.  In the latter case, eofmark is the
12121  * word which marks the end of the document and striptabs is true if
12122  * leading tabs should be stripped from the document.  The argument c
12123  * is the first character of the input token or document.
12124  *
12125  * Because C does not have internal subroutines, I have simulated them
12126  * using goto's to implement the subroutine linkage.  The following macros
12127  * will run code that appears at the end of readtoken1.
12128  */
12129 #define CHECKEND()      {goto checkend; checkend_return:;}
12130 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12131 #define PARSESUB()      {goto parsesub; parsesub_return:;}
12132 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
12133 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
12134 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
12135 static int
12136 readtoken1(int c, int syntax, char *eofmark, int striptabs)
12137 {
12138         /* NB: syntax parameter fits into smallint */
12139         /* c parameter is an unsigned char or PEOF or PEOA */
12140         char *out;
12141         size_t len;
12142         struct nodelist *bqlist;
12143         smallint quotef;
12144         smallint oldstyle;
12145         smallint pssyntax;   /* we are expanding a prompt string */
12146         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12147         /* syntax stack */
12148         struct synstack synbase = { };
12149         struct synstack *synstack = &synbase;
12150
12151 #if ENABLE_ASH_EXPAND_PRMT
12152         pssyntax = (syntax == PSSYNTAX);
12153         if (pssyntax)
12154                 syntax = DQSYNTAX;
12155 #else
12156         pssyntax = 0; /* constant */
12157 #endif
12158         synstack->syntax = syntax;
12159
12160         if (syntax == DQSYNTAX)
12161                 synstack->dblquote = 1;
12162         quotef = 0;
12163         bqlist = NULL;
12164
12165         STARTSTACKSTR(out);
12166  loop:
12167         /* For each line, until end of word */
12168         CHECKEND();     /* set c to PEOF if at end of here document */
12169         for (;;) {      /* until end of line or end of word */
12170                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12171                 switch (SIT(c, synstack->syntax)) {
12172                 case CNL:       /* '\n' */
12173                         if (synstack->syntax == BASESYNTAX
12174                          && !synstack->varnest
12175                         ) {
12176                                 goto endword;   /* exit outer loop */
12177                         }
12178                         USTPUTC(c, out);
12179                         nlprompt();
12180                         c = pgetc();
12181                         goto loop;              /* continue outer loop */
12182                 case CWORD:
12183                         USTPUTC(c, out);
12184                         break;
12185                 case CCTL:
12186 #if BASH_DOLLAR_SQUOTE
12187                         if (c == '\\' && bash_dollar_squote) {
12188                                 c = decode_dollar_squote();
12189                                 if (c == '\0') {
12190                                         /* skip $'\000', $'\x00' (like bash) */
12191                                         break;
12192                                 }
12193                                 if (c & 0x100) {
12194                                         /* Unknown escape. Encode as '\z' */
12195                                         c = (unsigned char)c;
12196                                         if (eofmark == NULL || synstack->dblquote)
12197                                                 USTPUTC(CTLESC, out);
12198                                         USTPUTC('\\', out);
12199                                 }
12200                         }
12201 #endif
12202                         if (!eofmark || synstack->dblquote || synstack->varnest)
12203                                 USTPUTC(CTLESC, out);
12204                         USTPUTC(c, out);
12205                         break;
12206                 case CBACK:     /* backslash */
12207                         c = pgetc_without_PEOA();
12208                         if (c == PEOF) {
12209                                 USTPUTC(CTLESC, out);
12210                                 USTPUTC('\\', out);
12211                                 pungetc();
12212                         } else if (c == '\n') {
12213                                 nlprompt();
12214                         } else {
12215                                 if (pssyntax && c == '$') {
12216                                         USTPUTC(CTLESC, out);
12217                                         USTPUTC('\\', out);
12218                                 }
12219                                 /* Backslash is retained if we are in "str"
12220                                  * and next char isn't dquote-special.
12221                                  */
12222                                 if (synstack->dblquote
12223                                  && c != '\\'
12224                                  && c != '`'
12225                                  && c != '$'
12226                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12227                                  && (c != '}' || !synstack->varnest)
12228                                 ) {
12229                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12230                                         USTPUTC('\\', out);
12231                                 }
12232                                 USTPUTC(CTLESC, out);
12233                                 USTPUTC(c, out);
12234                                 quotef = 1;
12235                         }
12236                         break;
12237                 case CSQUOTE:
12238                         synstack->syntax = SQSYNTAX;
12239  quotemark:
12240                         if (eofmark == NULL) {
12241                                 USTPUTC(CTLQUOTEMARK, out);
12242                         }
12243                         break;
12244                 case CDQUOTE:
12245                         synstack->syntax = DQSYNTAX;
12246                         synstack->dblquote = 1;
12247  toggledq:
12248                         if (synstack->varnest)
12249                                 synstack->innerdq ^= 1;
12250                         goto quotemark;
12251                 case CENDQUOTE:
12252                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12253                         if (eofmark != NULL && synstack->varnest == 0) {
12254                                 USTPUTC(c, out);
12255                                 break;
12256                         }
12257
12258                         if (synstack->dqvarnest == 0) {
12259                                 synstack->syntax = BASESYNTAX;
12260                                 synstack->dblquote = 0;
12261                         }
12262
12263                         quotef = 1;
12264
12265                         if (c == '"')
12266                                 goto toggledq;
12267
12268                         goto quotemark;
12269                 case CVAR:      /* '$' */
12270                         PARSESUB();             /* parse substitution */
12271                         break;
12272                 case CENDVAR:   /* '}' */
12273                         if (!synstack->innerdq && synstack->varnest > 0) {
12274                                 if (!--synstack->varnest && synstack->varpushed)
12275                                         synstack_pop(&synstack);
12276                                 else if (synstack->dqvarnest > 0)
12277                                         synstack->dqvarnest--;
12278                                 c = CTLENDVAR;
12279                         }
12280                         USTPUTC(c, out);
12281                         break;
12282 #if ENABLE_FEATURE_SH_MATH
12283                 case CLP:       /* '(' in arithmetic */
12284                         synstack->parenlevel++;
12285                         USTPUTC(c, out);
12286                         break;
12287                 case CRP:       /* ')' in arithmetic */
12288                         if (synstack->parenlevel > 0) {
12289                                 synstack->parenlevel--;
12290                         } else {
12291                                 if (pgetc_eatbnl() == ')') {
12292                                         c = CTLENDARI;
12293                                         synstack_pop(&synstack);
12294                                 } else {
12295                                         /*
12296                                          * unbalanced parens
12297                                          * (don't 2nd guess - no error)
12298                                          */
12299                                         pungetc();
12300                                 }
12301                         }
12302                         USTPUTC(c, out);
12303                         break;
12304 #endif
12305                 case CBQUOTE:   /* '`' */
12306                         if (checkkwd & CHKEOFMARK) {
12307                                 quotef = 1;
12308                                 USTPUTC('`', out);
12309                                 break;
12310                         }
12311
12312                         PARSEBACKQOLD();
12313                         break;
12314                 case CENDFILE:
12315                         goto endword;           /* exit outer loop */
12316                 case CIGN:
12317                         break;
12318                 default:
12319                         if (synstack->varnest == 0) {
12320 #if BASH_REDIR_OUTPUT
12321                                 if (c == '&') {
12322 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12323                                         if (pgetc() == '>')
12324                                                 c = 0x100 + '>'; /* flag &> */
12325                                         pungetc();
12326                                 }
12327 #endif
12328                                 goto endword;   /* exit outer loop */
12329                         }
12330                         IF_ASH_ALIAS(if (c != PEOA))
12331                                 USTPUTC(c, out);
12332                 }
12333                 c = pgetc();
12334         } /* for (;;) */
12335  endword:
12336
12337 #if ENABLE_FEATURE_SH_MATH
12338         if (synstack->syntax == ARISYNTAX)
12339                 raise_error_syntax("missing '))'");
12340 #endif
12341         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12342                 raise_error_syntax("unterminated quoted string");
12343         if (synstack->varnest != 0) {
12344                 /* { */
12345                 raise_error_syntax("missing '}'");
12346         }
12347         USTPUTC('\0', out);
12348         len = out - (char *)stackblock();
12349         out = stackblock();
12350         if (eofmark == NULL) {
12351                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12352                  && quotef == 0
12353                 ) {
12354                         if (isdigit_str9(out)) {
12355                                 PARSEREDIR(); /* passed as params: out, c */
12356                                 lasttoken = TREDIR;
12357                                 return lasttoken;
12358                         }
12359                         /* else: non-number X seen, interpret it
12360                          * as "NNNX>file" = "NNNX >file" */
12361                 }
12362                 pungetc();
12363         }
12364         quoteflag = quotef;
12365         backquotelist = bqlist;
12366         grabstackblock(len);
12367         wordtext = out;
12368         lasttoken = TWORD;
12369         return lasttoken;
12370 /* end of readtoken routine */
12371
12372 /*
12373  * Check to see whether we are at the end of the here document.  When this
12374  * is called, c is set to the first character of the next input line.  If
12375  * we are at the end of the here document, this routine sets the c to PEOF.
12376  */
12377 checkend: {
12378         if (realeofmark(eofmark)) {
12379                 int markloc;
12380                 char *p;
12381
12382 #if ENABLE_ASH_ALIAS
12383                 if (c == PEOA)
12384                         c = pgetc_without_PEOA();
12385 #endif
12386                 if (striptabs) {
12387                         while (c == '\t') {
12388                                 c = pgetc_without_PEOA();
12389                         }
12390                 }
12391
12392                 markloc = out - (char *)stackblock();
12393                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12394                         if (c != *p)
12395                                 goto more_heredoc;
12396
12397                         c = pgetc_without_PEOA();
12398                 }
12399
12400                 if (c == '\n' || c == PEOF) {
12401                         c = PEOF;
12402                         g_parsefile->linno++;
12403                         needprompt = doprompt;
12404                 } else {
12405                         int len_here;
12406
12407  more_heredoc:
12408                         p = (char *)stackblock() + markloc + 1;
12409                         len_here = out - p;
12410
12411                         if (len_here) {
12412                                 len_here -= (c >= PEOF);
12413                                 c = p[-1];
12414
12415                                 if (len_here) {
12416                                         char *str;
12417
12418                                         str = alloca(len_here + 1);
12419                                         *(char *)mempcpy(str, p, len_here) = '\0';
12420
12421                                         pushstring(str, NULL);
12422                                 }
12423                         }
12424                 }
12425
12426                 STADJUST((char *)stackblock() + markloc - out, out);
12427         }
12428         goto checkend_return;
12429 }
12430
12431 /*
12432  * Parse a redirection operator.  The variable "out" points to a string
12433  * specifying the fd to be redirected.  The variable "c" contains the
12434  * first character of the redirection operator.
12435  */
12436 parseredir: {
12437         /* out is already checked to be a valid number or "" */
12438         int fd = (*out == '\0' ? -1 : atoi(out));
12439         union node *np;
12440
12441         np = stzalloc(sizeof(struct nfile));
12442         if (c == '>') {
12443                 np->nfile.fd = 1;
12444                 c = pgetc_eatbnl();
12445                 if (c == '>')
12446                         np->type = NAPPEND;
12447                 else if (c == '|')
12448                         np->type = NCLOBBER;
12449                 else if (c == '&')
12450                         np->type = NTOFD;
12451                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12452                 else {
12453                         np->type = NTO;
12454                         pungetc();
12455                 }
12456         }
12457 #if BASH_REDIR_OUTPUT
12458         else if (c == 0x100 + '>') { /* this flags &> redirection */
12459                 np->nfile.fd = 1;
12460                 pgetc(); /* this is '>', no need to check */
12461                 np->type = NTO2;
12462         }
12463 #endif
12464         else { /* c == '<' */
12465                 /*np->nfile.fd = 0; - stzalloc did it */
12466                 c = pgetc_eatbnl();
12467                 switch (c) {
12468                 case '<':
12469                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12470                                 np = stzalloc(sizeof(struct nhere));
12471                                 /*np->nfile.fd = 0; - stzalloc did it */
12472                         }
12473                         np->type = NHERE;
12474                         heredoc = stzalloc(sizeof(struct heredoc));
12475                         heredoc->here = np;
12476                         c = pgetc_eatbnl();
12477                         if (c == '-') {
12478                                 heredoc->striptabs = 1;
12479                         } else {
12480                                 /*heredoc->striptabs = 0; - stzalloc did it */
12481                                 pungetc();
12482                         }
12483                         break;
12484
12485                 case '&':
12486                         np->type = NFROMFD;
12487                         break;
12488
12489                 case '>':
12490                         np->type = NFROMTO;
12491                         break;
12492
12493                 default:
12494                         np->type = NFROM;
12495                         pungetc();
12496                         break;
12497                 }
12498         }
12499         if (fd >= 0)
12500                 np->nfile.fd = fd;
12501         redirnode = np;
12502         goto parseredir_return;
12503 }
12504
12505 /*
12506  * Parse a substitution.  At this point, we have read the dollar sign
12507  * and nothing else.
12508  */
12509
12510 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12511  * (assuming ascii char codes, as the original implementation did) */
12512 #define is_special(c) \
12513         (((unsigned)(c) - 33 < 32) \
12514                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12515 parsesub: {
12516         unsigned char subtype;
12517         int typeloc;
12518
12519         c = pgetc_eatbnl();
12520         if ((checkkwd & CHKEOFMARK)
12521          || c > 255 /* PEOA or PEOF */
12522          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12523         ) {
12524 #if BASH_DOLLAR_SQUOTE
12525                 if (synstack->syntax != DQSYNTAX && c == '\'')
12526                         bash_dollar_squote = 1;
12527                 else
12528 #endif
12529                         USTPUTC('$', out);
12530                 pungetc();
12531         } else if (c == '(') {
12532                 /* $(command) or $((arith)) */
12533                 if (pgetc_eatbnl() == '(') {
12534 #if ENABLE_FEATURE_SH_MATH
12535                         PARSEARITH();
12536 #else
12537                         raise_error_syntax("support for $((arith)) is disabled");
12538 #endif
12539                 } else {
12540                         pungetc();
12541                         PARSEBACKQNEW();
12542                 }
12543         } else {
12544                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12545                 smalluint newsyn = synstack->syntax;
12546
12547                 USTPUTC(CTLVAR, out);
12548                 typeloc = out - (char *)stackblock();
12549                 STADJUST(1, out);
12550                 subtype = VSNORMAL;
12551                 if (c == '{') {
12552                         c = pgetc_eatbnl();
12553                         subtype = 0;
12554                 }
12555  varname:
12556                 if (is_name(c)) {
12557                         /* $[{[#]]NAME[}] */
12558                         do {
12559                                 STPUTC(c, out);
12560                                 c = pgetc_eatbnl();
12561                         } while (is_in_name(c));
12562                 } else if (isdigit(c)) {
12563                         /* $[{[#]]NUM[}] */
12564                         do {
12565                                 STPUTC(c, out);
12566                                 c = pgetc_eatbnl();
12567                         } while (isdigit(c));
12568                 } else if (c != '}') {
12569                         /* $[{[#]]<specialchar>[}] */
12570                         int cc = c;
12571
12572                         c = pgetc_eatbnl();
12573                         if (!subtype && cc == '#') {
12574                                 subtype = VSLENGTH;
12575                                 if (c == '_' || isalnum(c))
12576                                         goto varname;
12577                                 cc = c;
12578                                 c = pgetc_eatbnl();
12579                                 if (cc == '}' || c != '}') {
12580                                         pungetc();
12581                                         subtype = 0;
12582                                         c = cc;
12583                                         cc = '#';
12584                                 }
12585                         }
12586
12587                         if (!is_special(cc)) {
12588                                 if (subtype == VSLENGTH)
12589                                         subtype = 0;
12590                                 goto badsub;
12591                         }
12592
12593                         USTPUTC(cc, out);
12594                 } else
12595                         goto badsub;
12596
12597                 if (c != '}' && subtype == VSLENGTH) {
12598                         /* ${#VAR didn't end with } */
12599                         goto badsub;
12600                 }
12601
12602                 if (subtype == 0) {
12603                         static const char types[] ALIGN1 = "}-+?=";
12604                         /* ${VAR...} but not $VAR or ${#VAR} */
12605                         /* c == first char after VAR */
12606                         int cc = c;
12607
12608                         switch (c) {
12609                         case ':':
12610                                 c = pgetc_eatbnl();
12611 #if BASH_SUBSTR
12612                                 /* This check is only needed to not misinterpret
12613                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12614                                  * constructs.
12615                                  */
12616                                 if (!strchr(types, c)) {
12617                                         subtype = VSSUBSTR;
12618                                         pungetc();
12619                                         break; /* "goto badsub" is bigger (!) */
12620                                 }
12621 #endif
12622                                 subtype = VSNUL;
12623                                 /*FALLTHROUGH*/
12624                         default: {
12625                                 const char *p = strchr(types, c);
12626                                 if (p == NULL)
12627                                         break;
12628                                 subtype |= p - types + VSNORMAL;
12629                                 break;
12630                         }
12631                         case '%':
12632                         case '#':
12633                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12634                                 c = pgetc_eatbnl();
12635                                 if (c == cc)
12636                                         subtype++;
12637                                 else
12638                                         pungetc();
12639
12640                                 newsyn = BASESYNTAX;
12641                                 break;
12642 #if BASH_PATTERN_SUBST
12643                         case '/':
12644                                 /* ${v/[/]pattern/repl} */
12645 //TODO: encode pattern and repl separately.
12646 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12647 // are broken (should print "ONE")
12648                                 subtype = VSREPLACE;
12649                                 newsyn = BASESYNTAX;
12650                                 c = pgetc_eatbnl();
12651                                 if (c != '/')
12652                                         goto badsub;
12653                                 subtype++; /* VSREPLACEALL */
12654                                 break;
12655 #endif
12656                         }
12657                 } else {
12658  badsub:
12659                         pungetc();
12660                 }
12661
12662                 if (newsyn == ARISYNTAX)
12663                         newsyn = DQSYNTAX;
12664
12665                 if ((newsyn != synstack->syntax || synstack->innerdq)
12666                  && subtype != VSNORMAL
12667                 ) {
12668                         synstack_push(&synstack,
12669                                 synstack->prev ?: alloca(sizeof(*synstack)),
12670                                 newsyn);
12671
12672                         synstack->varpushed = 1;
12673                         synstack->dblquote = newsyn != BASESYNTAX;
12674                 }
12675
12676                 ((unsigned char *)stackblock())[typeloc] = subtype;
12677                 if (subtype != VSNORMAL) {
12678                         synstack->varnest++;
12679                         if (synstack->dblquote)
12680                                 synstack->dqvarnest++;
12681                 }
12682                 STPUTC('=', out);
12683         }
12684         goto parsesub_return;
12685 }
12686
12687 /*
12688  * Called to parse command substitutions.  Newstyle is set if the command
12689  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12690  * list of commands (passed by reference), and savelen is the number of
12691  * characters on the top of the stack which must be preserved.
12692  */
12693 parsebackq: {
12694         struct nodelist **nlpp;
12695         union node *n;
12696         char *str;
12697         size_t savelen;
12698         smallint saveprompt = 0;
12699
12700         str = NULL;
12701         savelen = out - (char *)stackblock();
12702         if (savelen > 0) {
12703                 /*
12704                  * FIXME: this can allocate very large block on stack and SEGV.
12705                  * Example:
12706                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12707                  * allocates 100kb for every command subst. With about
12708                  * a hundred command substitutions stack overflows.
12709                  * With larger prepended string, SEGV happens sooner.
12710                  */
12711                 str = alloca(savelen);
12712                 memcpy(str, stackblock(), savelen);
12713         }
12714
12715         if (oldstyle) {
12716                 /* We must read until the closing backquote, giving special
12717                  * treatment to some slashes, and then push the string and
12718                  * reread it as input, interpreting it normally.
12719                  */
12720                 char *pout;
12721                 size_t psavelen;
12722                 char *pstr;
12723
12724                 STARTSTACKSTR(pout);
12725                 for (;;) {
12726                         int pc;
12727
12728                         setprompt_if(needprompt, 2);
12729                         pc = pgetc_eatbnl();
12730                         switch (pc) {
12731                         case '`':
12732                                 goto done;
12733
12734                         case '\\':
12735                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12736                                 if (pc != '\\' && pc != '`' && pc != '$'
12737                                  && (!synstack->dblquote || pc != '"')
12738                                 ) {
12739                                         STPUTC('\\', pout);
12740                                 }
12741                                 if (pc <= 255 /* not PEOA or PEOF */) {
12742                                         break;
12743                                 }
12744                                 /* fall through */
12745
12746                         case PEOF:
12747                         IF_ASH_ALIAS(case PEOA:)
12748                                 raise_error_syntax("EOF in backquote substitution");
12749
12750                         case '\n':
12751                                 nlnoprompt();
12752                                 break;
12753
12754                         default:
12755                                 break;
12756                         }
12757                         STPUTC(pc, pout);
12758                 }
12759  done:
12760                 STPUTC('\0', pout);
12761                 psavelen = pout - (char *)stackblock();
12762                 if (psavelen > 0) {
12763                         pstr = grabstackstr(pout);
12764                         setinputstring(pstr);
12765                 }
12766         }
12767         nlpp = &bqlist;
12768         while (*nlpp)
12769                 nlpp = &(*nlpp)->next;
12770         *nlpp = stzalloc(sizeof(**nlpp));
12771         /* (*nlpp)->next = NULL; - stzalloc did it */
12772
12773         if (oldstyle) {
12774                 saveprompt = doprompt;
12775                 doprompt = 0;
12776         }
12777
12778         n = list(2);
12779
12780         if (oldstyle)
12781                 doprompt = saveprompt;
12782         else if (readtoken() != TRP)
12783                 raise_error_unexpected_syntax(TRP);
12784
12785         (*nlpp)->n = n;
12786         if (oldstyle) {
12787                 /*
12788                  * Start reading from old file again, ignoring any pushed back
12789                  * tokens left from the backquote parsing
12790                  */
12791                 popfile();
12792                 tokpushback = 0;
12793         }
12794         while (stackblocksize() <= savelen)
12795                 growstackblock();
12796         STARTSTACKSTR(out);
12797         if (str) {
12798                 memcpy(out, str, savelen);
12799                 STADJUST(savelen, out);
12800         }
12801         USTPUTC(CTLBACKQ, out);
12802         if (oldstyle)
12803                 goto parsebackq_oldreturn;
12804         goto parsebackq_newreturn;
12805 }
12806
12807 #if ENABLE_FEATURE_SH_MATH
12808 /*
12809  * Parse an arithmetic expansion (indicate start of one and set state)
12810  */
12811 parsearith: {
12812
12813         synstack_push(&synstack,
12814                         synstack->prev ?: alloca(sizeof(*synstack)),
12815                         ARISYNTAX);
12816         synstack->dblquote = 1;
12817         USTPUTC(CTLARI, out);
12818         goto parsearith_return;
12819 }
12820 #endif
12821 } /* end of readtoken */
12822
12823 /*
12824  * Read the next input token.
12825  * If the token is a word, we set backquotelist to the list of cmds in
12826  *      backquotes.  We set quoteflag to true if any part of the word was
12827  *      quoted.
12828  * If the token is TREDIR, then we set redirnode to a structure containing
12829  *      the redirection.
12830  *
12831  * [Change comment:  here documents and internal procedures]
12832  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12833  *  word parsing code into a separate routine.  In this case, readtoken
12834  *  doesn't need to have any internal procedures, but parseword does.
12835  *  We could also make parseoperator in essence the main routine, and
12836  *  have parseword (readtoken1?) handle both words and redirection.]
12837  */
12838 #define NEW_xxreadtoken
12839 #ifdef NEW_xxreadtoken
12840 /* singles must be first! */
12841 static const char xxreadtoken_chars[7] ALIGN1 = {
12842         '\n', '(', ')', /* singles */
12843         '&', '|', ';',  /* doubles */
12844         0
12845 };
12846
12847 #define xxreadtoken_singles 3
12848 #define xxreadtoken_doubles 3
12849
12850 static const char xxreadtoken_tokens[] ALIGN1 = {
12851         TNL, TLP, TRP,          /* only single occurrence allowed */
12852         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12853         TEOF,                   /* corresponds to trailing nul */
12854         TAND, TOR, TENDCASE     /* if double occurrence */
12855 };
12856
12857 static int
12858 xxreadtoken(void)
12859 {
12860         int c;
12861
12862         if (tokpushback) {
12863                 tokpushback = 0;
12864                 return lasttoken;
12865         }
12866         setprompt_if(needprompt, 2);
12867         for (;;) {                      /* until token or start of word found */
12868                 c = pgetc_eatbnl();
12869                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12870                         continue;
12871
12872                 if (c == '#') {
12873                         while ((c = pgetc()) != '\n' && c != PEOF)
12874                                 continue;
12875                         pungetc();
12876                 } else if (c == '\\') {
12877                         break; /* return readtoken1(...) */
12878                 } else {
12879                         const char *p;
12880
12881                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12882                         if (c != PEOF) {
12883                                 if (c == '\n') {
12884                                         nlnoprompt();
12885                                 }
12886
12887                                 p = strchr(xxreadtoken_chars, c);
12888                                 if (p == NULL)
12889                                         break; /* return readtoken1(...) */
12890
12891                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12892                                         int cc = pgetc_eatbnl();
12893                                         if (cc == c) {    /* double occurrence? */
12894                                                 p += xxreadtoken_doubles + 1;
12895                                         } else {
12896                                                 pungetc();
12897 #if BASH_REDIR_OUTPUT
12898                                                 if (c == '&' && cc == '>') /* &> */
12899                                                         break; /* return readtoken1(...) */
12900 #endif
12901                                         }
12902                                 }
12903                         }
12904                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12905                         return lasttoken;
12906                 }
12907         } /* for (;;) */
12908
12909         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12910 }
12911 #else /* old xxreadtoken */
12912 #define RETURN(token)   return lasttoken = token
12913 static int
12914 xxreadtoken(void)
12915 {
12916         int c;
12917
12918         if (tokpushback) {
12919                 tokpushback = 0;
12920                 return lasttoken;
12921         }
12922         setprompt_if(needprompt, 2);
12923         for (;;) {      /* until token or start of word found */
12924                 c = pgetc_eatbnl();
12925                 switch (c) {
12926                 case ' ': case '\t':
12927                 IF_ASH_ALIAS(case PEOA:)
12928                         continue;
12929                 case '#':
12930                         while ((c = pgetc()) != '\n' && c != PEOF)
12931                                 continue;
12932                         pungetc();
12933                         continue;
12934                 case '\n':
12935                         nlnoprompt();
12936                         RETURN(TNL);
12937                 case PEOF:
12938                         RETURN(TEOF);
12939                 case '&':
12940                         if (pgetc_eatbnl() == '&')
12941                                 RETURN(TAND);
12942                         pungetc();
12943                         RETURN(TBACKGND);
12944                 case '|':
12945                         if (pgetc_eatbnl() == '|')
12946                                 RETURN(TOR);
12947                         pungetc();
12948                         RETURN(TPIPE);
12949                 case ';':
12950                         if (pgetc_eatbnl() == ';')
12951                                 RETURN(TENDCASE);
12952                         pungetc();
12953                         RETURN(TSEMI);
12954                 case '(':
12955                         RETURN(TLP);
12956                 case ')':
12957                         RETURN(TRP);
12958                 }
12959                 break;
12960         }
12961         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12962 #undef RETURN
12963 }
12964 #endif /* old xxreadtoken */
12965
12966 static int
12967 readtoken(void)
12968 {
12969         int t;
12970         int kwd = checkkwd;
12971 #if DEBUG
12972         smallint alreadyseen = tokpushback;
12973 #endif
12974
12975 #if ENABLE_ASH_ALIAS
12976  top:
12977 #endif
12978
12979         t = xxreadtoken();
12980
12981         /*
12982          * eat newlines
12983          */
12984         if (kwd & CHKNL) {
12985                 while (t == TNL) {
12986                         parseheredoc();
12987                         t = xxreadtoken();
12988                 }
12989         }
12990
12991         if (t != TWORD || quoteflag) {
12992                 goto out;
12993         }
12994
12995         /*
12996          * check for keywords
12997          */
12998         if (kwd & CHKKWD) {
12999                 const char *const *pp;
13000
13001                 pp = findkwd(wordtext);
13002                 if (pp) {
13003                         lasttoken = t = pp - tokname_array;
13004                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13005                         goto out;
13006                 }
13007         }
13008
13009         if (checkkwd & CHKALIAS) {
13010 #if ENABLE_ASH_ALIAS
13011                 struct alias *ap;
13012                 ap = lookupalias(wordtext, 1);
13013                 if (ap != NULL) {
13014                         if (*ap->val) {
13015                                 pushstring(ap->val, ap);
13016                         }
13017                         goto top;
13018                 }
13019 #endif
13020         }
13021  out:
13022         checkkwd = 0;
13023 #if DEBUG
13024         if (!alreadyseen)
13025                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13026         else
13027                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13028 #endif
13029         return t;
13030 }
13031
13032 static int
13033 peektoken(void)
13034 {
13035         int t;
13036
13037         t = readtoken();
13038         tokpushback = 1;
13039         return t;
13040 }
13041
13042 /*
13043  * Read and parse a command.  Returns NODE_EOF on end of file.
13044  * (NULL is a valid parse tree indicating a blank line.)
13045  */
13046 static union node *
13047 parsecmd(int interact)
13048 {
13049         tokpushback = 0;
13050         checkkwd = 0;
13051         heredoclist = 0;
13052         doprompt = interact;
13053         setprompt_if(doprompt, doprompt);
13054         needprompt = 0;
13055         return list(1);
13056 }
13057
13058 /*
13059  * Input any here documents.
13060  */
13061 static void
13062 parseheredoc(void)
13063 {
13064         struct heredoc *here;
13065         union node *n;
13066
13067         here = heredoclist;
13068         heredoclist = NULL;
13069
13070         while (here) {
13071                 tokpushback = 0;
13072                 setprompt_if(needprompt, 2);
13073                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
13074                                 here->eofmark, here->striptabs);
13075                 n = stzalloc(sizeof(struct narg));
13076                 n->narg.type = NARG;
13077                 /*n->narg.next = NULL; - stzalloc did it */
13078                 n->narg.text = wordtext;
13079                 n->narg.backquote = backquotelist;
13080                 here->here->nhere.doc = n;
13081                 here = here->next;
13082         }
13083 }
13084
13085
13086 static const char *
13087 expandstr(const char *ps, int syntax_type)
13088 {
13089         union node n;
13090         int saveprompt;
13091         struct parsefile *file_stop = g_parsefile;
13092         volatile int saveint;
13093         struct jmploc *volatile savehandler = exception_handler;
13094         struct jmploc jmploc;
13095
13096         /* XXX Fix (char *) cast. */
13097         setinputstring((char *)ps);
13098
13099         saveprompt = doprompt;
13100         doprompt = 0;
13101
13102         /* readtoken1() might die horribly.
13103          * Try a prompt with syntactically wrong command:
13104          * PS1='$(date "+%H:%M:%S) > '
13105          */
13106         SAVE_INT(saveint);
13107         if (setjmp(jmploc.loc) == 0) {
13108                 exception_handler = &jmploc;
13109                 readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13110         }
13111         exception_handler = savehandler;
13112         RESTORE_INT(saveint);
13113
13114         doprompt = saveprompt;
13115
13116         /* Try: PS1='`xxx(`' */
13117         unwindfiles(file_stop);
13118
13119         n.narg.type = NARG;
13120         n.narg.next = NULL;
13121         n.narg.text = wordtext;
13122         n.narg.backquote = backquotelist;
13123
13124         /* expandarg() might fail too:
13125          * PS1='$((123+))'
13126          */
13127         SAVE_INT(saveint);
13128         if (setjmp(jmploc.loc) == 0) {
13129                 exception_handler = &jmploc;
13130                 expandarg(&n, NULL, EXP_QUOTED);
13131         } else if (exception_type == EXEXIT) {
13132                 exitshell();
13133         }
13134         exception_handler = savehandler;
13135         RESTORE_INT(saveint);
13136
13137         return stackblock();
13138 }
13139
13140 static inline int
13141 parser_eof(void)
13142 {
13143         return tokpushback && lasttoken == TEOF;
13144 }
13145
13146 /*
13147  * Execute a command or commands contained in a string.
13148  */
13149 static int
13150 evalstring(char *s, int flags)
13151 {
13152         struct jmploc *volatile savehandler;
13153         struct jmploc jmploc;
13154         int ex;
13155
13156         union node *n;
13157         struct stackmark smark;
13158         int status;
13159
13160         s = sstrdup(s);
13161         setinputstring(s);
13162         setstackmark(&smark);
13163
13164         status = 0;
13165         /* On exception inside execution loop, we must popfile().
13166          * Try interactively:
13167          *      readonly a=a
13168          *      command eval "a=b"  # throws "is read only" error
13169          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13170          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13171          */
13172         savehandler = exception_handler;
13173         ex = setjmp(jmploc.loc);
13174         if (ex)
13175                 goto out;
13176         exception_handler = &jmploc;
13177
13178         while ((n = parsecmd(0)) != NODE_EOF) {
13179                 int i;
13180
13181                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13182                 if (n)
13183                         status = i;
13184                 popstackmark(&smark);
13185                 if (evalskip)
13186                         break;
13187         }
13188  out:
13189         popstackmark(&smark);
13190         popfile();
13191         stunalloc(s);
13192
13193         exception_handler = savehandler;
13194         if (ex)
13195                 longjmp(exception_handler->loc, ex);
13196
13197         return status;
13198 }
13199
13200 /*
13201  * The eval command.
13202  */
13203 static int FAST_FUNC
13204 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13205 {
13206         char *p;
13207         char *concat;
13208
13209         if (argv[1]) {
13210                 p = argv[1];
13211                 argv += 2;
13212                 if (argv[0]) {
13213                         STARTSTACKSTR(concat);
13214                         for (;;) {
13215                                 concat = stack_putstr(p, concat);
13216                                 p = *argv++;
13217                                 if (p == NULL)
13218                                         break;
13219                                 STPUTC(' ', concat);
13220                         }
13221                         STPUTC('\0', concat);
13222                         p = grabstackstr(concat);
13223                 }
13224                 return evalstring(p, flags & EV_TESTED);
13225         }
13226         return 0;
13227 }
13228
13229 /*
13230  * Read and execute commands.
13231  * "Top" is nonzero for the top level command loop;
13232  * it turns on prompting if the shell is interactive.
13233  */
13234 static int
13235 cmdloop(int top)
13236 {
13237         union node *n;
13238         struct stackmark smark;
13239         int inter;
13240         int status = 0;
13241         int numeof = 0;
13242
13243         TRACE(("cmdloop(%d) called\n", top));
13244         for (;;) {
13245                 int skip;
13246
13247                 setstackmark(&smark);
13248 #if JOBS
13249                 if (doing_jobctl)
13250                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13251 #endif
13252                 inter = 0;
13253                 if (iflag && top) {
13254                         inter++;
13255                         chkmail();
13256                 }
13257                 n = parsecmd(inter);
13258 #if DEBUG
13259                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13260                         showtree(n);
13261 #endif
13262                 if (n == NODE_EOF) {
13263                         if (!top || numeof >= 50)
13264                                 break;
13265                         if (!stoppedjobs()) {
13266                                 if (!Iflag)
13267                                         break;
13268                                 out2str("\nUse \"exit\" to leave shell.\n");
13269                         }
13270                         numeof++;
13271                 } else if (nflag == 0) {
13272                         int i;
13273
13274                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13275                         job_warning >>= 1;
13276                         numeof = 0;
13277                         i = evaltree(n, 0);
13278                         if (n)
13279                                 status = i;
13280                 }
13281                 popstackmark(&smark);
13282                 skip = evalskip;
13283
13284                 if (skip) {
13285                         evalskip &= ~SKIPFUNC;
13286                         break;
13287                 }
13288         }
13289         return status;
13290 }
13291
13292 /*
13293  * Take commands from a file.  To be compatible we should do a path
13294  * search for the file, which is necessary to find sub-commands.
13295  */
13296 static char *
13297 find_dot_file(char *name)
13298 {
13299         char *fullname;
13300         const char *path = pathval();
13301         struct stat statb;
13302
13303         /* don't try this for absolute or relative paths */
13304         if (strchr(name, '/'))
13305                 return name;
13306
13307         while ((fullname = path_advance(&path, name)) != NULL) {
13308                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13309                         /*
13310                          * Don't bother freeing here, since it will
13311                          * be freed by the caller.
13312                          */
13313                         return fullname;
13314                 }
13315                 if (fullname != name)
13316                         stunalloc(fullname);
13317         }
13318         /* not found in PATH */
13319
13320 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13321         return name;
13322 #else
13323         ash_msg_and_raise_error("%s: not found", name);
13324         /* NOTREACHED */
13325 #endif
13326 }
13327
13328 static int FAST_FUNC
13329 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13330 {
13331         /* "false; . empty_file; echo $?" should print 0, not 1: */
13332         int status = 0;
13333         char *fullname;
13334         char **argv;
13335         char *args_need_save;
13336         volatile struct shparam saveparam;
13337
13338 //???
13339 //      struct strlist *sp;
13340 //      for (sp = cmdenviron; sp; sp = sp->next)
13341 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13342
13343         nextopt(nullstr); /* handle possible "--" */
13344         argv = argptr;
13345
13346         if (!argv[0]) {
13347                 /* bash says: "bash: .: filename argument required" */
13348                 return 2; /* bash compat */
13349         }
13350
13351         /* This aborts if file isn't found, which is POSIXly correct.
13352          * bash returns exitcode 1 instead.
13353          */
13354         fullname = find_dot_file(argv[0]);
13355         argv++;
13356         args_need_save = argv[0];
13357         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13358                 int argc;
13359                 saveparam = shellparam;
13360                 shellparam.malloced = 0;
13361                 argc = 1;
13362                 while (argv[argc])
13363                         argc++;
13364                 shellparam.nparam = argc;
13365                 shellparam.p = argv;
13366         };
13367
13368         /* This aborts if file can't be opened, which is POSIXly correct.
13369          * bash returns exitcode 1 instead.
13370          */
13371         setinputfile(fullname, INPUT_PUSH_FILE);
13372         commandname = fullname;
13373         status = cmdloop(0);
13374         popfile();
13375
13376         if (args_need_save) {
13377                 freeparam(&shellparam);
13378                 shellparam = saveparam;
13379         };
13380
13381         return status;
13382 }
13383
13384 static int FAST_FUNC
13385 exitcmd(int argc UNUSED_PARAM, char **argv)
13386 {
13387         if (stoppedjobs())
13388                 return 0;
13389         if (argv[1])
13390                 exitstatus = number(argv[1]);
13391         raise_exception(EXEXIT);
13392         /* NOTREACHED */
13393 }
13394
13395 /*
13396  * Read a file containing shell functions.
13397  */
13398 static void
13399 readcmdfile(char *name)
13400 {
13401         setinputfile(name, INPUT_PUSH_FILE);
13402         cmdloop(0);
13403         popfile();
13404 }
13405
13406
13407 /* ============ find_command inplementation */
13408
13409 /*
13410  * Resolve a command name.  If you change this routine, you may have to
13411  * change the shellexec routine as well.
13412  */
13413 static void
13414 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13415 {
13416         struct tblentry *cmdp;
13417         int idx;
13418         int prev;
13419         char *fullname;
13420         struct stat statb;
13421         int e;
13422         int updatetbl;
13423         struct builtincmd *bcmd;
13424
13425         /* If name contains a slash, don't use PATH or hash table */
13426         if (strchr(name, '/') != NULL) {
13427                 entry->u.index = -1;
13428                 if (act & DO_ABS) {
13429                         while (stat(name, &statb) < 0) {
13430 #ifdef SYSV
13431                                 if (errno == EINTR)
13432                                         continue;
13433 #endif
13434                                 entry->cmdtype = CMDUNKNOWN;
13435                                 return;
13436                         }
13437                 }
13438                 entry->cmdtype = CMDNORMAL;
13439                 return;
13440         }
13441
13442 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13443
13444         updatetbl = (path == pathval());
13445         if (!updatetbl) {
13446                 act |= DO_ALTPATH;
13447                 if (strstr(path, "%builtin") != NULL)
13448                         act |= DO_ALTBLTIN;
13449         }
13450
13451         /* If name is in the table, check answer will be ok */
13452         cmdp = cmdlookup(name, 0);
13453         if (cmdp != NULL) {
13454                 int bit;
13455
13456                 switch (cmdp->cmdtype) {
13457                 default:
13458 #if DEBUG
13459                         abort();
13460 #endif
13461                 case CMDNORMAL:
13462                         bit = DO_ALTPATH;
13463                         break;
13464                 case CMDFUNCTION:
13465                         bit = DO_NOFUNC;
13466                         break;
13467                 case CMDBUILTIN:
13468                         bit = DO_ALTBLTIN;
13469                         break;
13470                 }
13471                 if (act & bit) {
13472                         updatetbl = 0;
13473                         cmdp = NULL;
13474                 } else if (cmdp->rehash == 0)
13475                         /* if not invalidated by cd, we're done */
13476                         goto success;
13477         }
13478
13479         /* If %builtin not in path, check for builtin next */
13480         bcmd = find_builtin(name);
13481         if (bcmd) {
13482                 if (IS_BUILTIN_REGULAR(bcmd))
13483                         goto builtin_success;
13484                 if (act & DO_ALTPATH) {
13485                         if (!(act & DO_ALTBLTIN))
13486                                 goto builtin_success;
13487                 } else if (builtinloc <= 0) {
13488                         goto builtin_success;
13489                 }
13490         }
13491
13492 #if ENABLE_FEATURE_SH_STANDALONE
13493         {
13494                 int applet_no = find_applet_by_name(name);
13495                 if (applet_no >= 0) {
13496                         entry->cmdtype = CMDNORMAL;
13497                         entry->u.index = -2 - applet_no;
13498                         return;
13499                 }
13500         }
13501 #endif
13502
13503         /* We have to search path. */
13504         prev = -1;              /* where to start */
13505         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13506                 if (cmdp->cmdtype == CMDBUILTIN)
13507                         prev = builtinloc;
13508                 else
13509                         prev = cmdp->param.index;
13510         }
13511
13512         e = ENOENT;
13513         idx = -1;
13514  loop:
13515         while ((fullname = path_advance(&path, name)) != NULL) {
13516                 stunalloc(fullname);
13517                 /* NB: code below will still use fullname
13518                  * despite it being "unallocated" */
13519                 idx++;
13520                 if (pathopt) {
13521                         if (prefix(pathopt, "builtin")) {
13522                                 if (bcmd)
13523                                         goto builtin_success;
13524                                 continue;
13525                         }
13526                         if ((act & DO_NOFUNC)
13527                          || !prefix(pathopt, "func")
13528                         ) {     /* ignore unimplemented options */
13529                                 continue;
13530                         }
13531                 }
13532                 /* if rehash, don't redo absolute path names */
13533                 if (fullname[0] == '/' && idx <= prev) {
13534                         if (idx < prev)
13535                                 continue;
13536                         TRACE(("searchexec \"%s\": no change\n", name));
13537                         goto success;
13538                 }
13539                 while (stat(fullname, &statb) < 0) {
13540 #ifdef SYSV
13541                         if (errno == EINTR)
13542                                 continue;
13543 #endif
13544                         if (errno != ENOENT && errno != ENOTDIR)
13545                                 e = errno;
13546                         goto loop;
13547                 }
13548                 e = EACCES;     /* if we fail, this will be the error */
13549                 if (!S_ISREG(statb.st_mode))
13550                         continue;
13551                 if (pathopt) {          /* this is a %func directory */
13552                         stalloc(strlen(fullname) + 1);
13553                         /* NB: stalloc will return space pointed by fullname
13554                          * (because we don't have any intervening allocations
13555                          * between stunalloc above and this stalloc) */
13556                         readcmdfile(fullname);
13557                         cmdp = cmdlookup(name, 0);
13558                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13559                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13560                         stunalloc(fullname);
13561                         goto success;
13562                 }
13563                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13564                 if (!updatetbl) {
13565                         entry->cmdtype = CMDNORMAL;
13566                         entry->u.index = idx;
13567                         return;
13568                 }
13569                 INT_OFF;
13570                 cmdp = cmdlookup(name, 1);
13571                 cmdp->cmdtype = CMDNORMAL;
13572                 cmdp->param.index = idx;
13573                 INT_ON;
13574                 goto success;
13575         }
13576
13577         /* We failed.  If there was an entry for this command, delete it */
13578         if (cmdp && updatetbl)
13579                 delete_cmd_entry();
13580         if (act & DO_ERR) {
13581 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13582                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13583                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13584                         char *argv[3];
13585                         argv[0] = (char*) "command_not_found_handle";
13586                         argv[1] = name;
13587                         argv[2] = NULL;
13588                         evalfun(hookp->param.func, 2, argv, 0);
13589                         entry->cmdtype = CMDUNKNOWN;
13590                         return;
13591                 }
13592 #endif
13593                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13594         }
13595         entry->cmdtype = CMDUNKNOWN;
13596         return;
13597
13598  builtin_success:
13599         if (!updatetbl) {
13600                 entry->cmdtype = CMDBUILTIN;
13601                 entry->u.cmd = bcmd;
13602                 return;
13603         }
13604         INT_OFF;
13605         cmdp = cmdlookup(name, 1);
13606         cmdp->cmdtype = CMDBUILTIN;
13607         cmdp->param.cmd = bcmd;
13608         INT_ON;
13609  success:
13610         cmdp->rehash = 0;
13611         entry->cmdtype = cmdp->cmdtype;
13612         entry->u = cmdp->param;
13613 }
13614
13615
13616 /*
13617  * The trap builtin.
13618  */
13619 static int FAST_FUNC
13620 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13621 {
13622         char *action;
13623         char **ap;
13624         int signo, exitcode;
13625
13626         nextopt(nullstr);
13627         ap = argptr;
13628         if (!*ap) {
13629                 for (signo = 0; signo < NSIG; signo++) {
13630                         char *tr = trap_ptr[signo];
13631                         if (tr) {
13632                                 /* note: bash adds "SIG", but only if invoked
13633                                  * as "bash". If called as "sh", or if set -o posix,
13634                                  * then it prints short signal names.
13635                                  * We are printing short names: */
13636                                 out1fmt("trap -- %s %s\n",
13637                                                 single_quote(tr),
13638                                                 get_signame(signo));
13639                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13640                  * In this case, we will exit very soon, no need to free(). */
13641                                 /* if (trap_ptr != trap && tp[0]) */
13642                                 /*      free(tr); */
13643                         }
13644                 }
13645                 /*
13646                 if (trap_ptr != trap) {
13647                         free(trap_ptr);
13648                         trap_ptr = trap;
13649                 }
13650                 */
13651                 return 0;
13652         }
13653
13654         /* Why the second check?
13655          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13656          * In this case, NUM is signal no, not an action.
13657          */
13658         action = NULL;
13659         if (ap[1] && !is_number(ap[0]))
13660                 action = *ap++;
13661
13662         exitcode = 0;
13663         while (*ap) {
13664                 signo = get_signum(*ap);
13665                 if (signo < 0) {
13666                         /* Mimic bash message exactly */
13667                         ash_msg("%s: invalid signal specification", *ap);
13668                         exitcode = 1;
13669                         goto next;
13670                 }
13671                 INT_OFF;
13672                 if (action) {
13673                         if (LONE_DASH(action))
13674                                 action = NULL;
13675                         else {
13676                                 if (action[0]) /* not NULL and not "" and not "-" */
13677                                         may_have_traps = 1;
13678                                 action = ckstrdup(action);
13679                         }
13680                 }
13681                 free(trap[signo]);
13682                 trap[signo] = action;
13683                 if (signo != 0)
13684                         setsignal(signo);
13685                 INT_ON;
13686  next:
13687                 ap++;
13688         }
13689         return exitcode;
13690 }
13691
13692
13693 /* ============ Builtins */
13694
13695 #if ENABLE_ASH_HELP
13696 static int FAST_FUNC
13697 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13698 {
13699         unsigned col;
13700         unsigned i;
13701
13702         out1fmt(
13703                 "Built-in commands:\n"
13704                 "------------------\n");
13705         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13706                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13707                                         builtintab[i].name + 1);
13708                 if (col > 60) {
13709                         out1fmt("\n");
13710                         col = 0;
13711                 }
13712         }
13713 # if ENABLE_FEATURE_SH_STANDALONE
13714         {
13715                 const char *a = applet_names;
13716                 while (*a) {
13717                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13718                         if (col > 60) {
13719                                 out1fmt("\n");
13720                                 col = 0;
13721                         }
13722                         while (*a++ != '\0')
13723                                 continue;
13724                 }
13725         }
13726 # endif
13727         newline_and_flush(stdout);
13728         return EXIT_SUCCESS;
13729 }
13730 #endif
13731
13732 #if MAX_HISTORY
13733 static int FAST_FUNC
13734 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13735 {
13736         if (line_input_state)
13737                 show_history(line_input_state);
13738         return EXIT_SUCCESS;
13739 }
13740 #endif
13741
13742 /*
13743  * The export and readonly commands.
13744  */
13745 static int FAST_FUNC
13746 exportcmd(int argc UNUSED_PARAM, char **argv)
13747 {
13748         struct var *vp;
13749         char *name;
13750         const char *p;
13751         char **aptr;
13752         char opt;
13753         int flag;
13754         int flag_off;
13755
13756         /* "readonly" in bash accepts, but ignores -n.
13757          * We do the same: it saves a conditional in nextopt's param.
13758          */
13759         flag_off = 0;
13760         while ((opt = nextopt("np")) != '\0') {
13761                 if (opt == 'n')
13762                         flag_off = VEXPORT;
13763         }
13764         flag = VEXPORT;
13765         if (argv[0][0] == 'r') {
13766                 flag = VREADONLY;
13767                 flag_off = 0; /* readonly ignores -n */
13768         }
13769         flag_off = ~flag_off;
13770
13771         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13772         {
13773                 aptr = argptr;
13774                 name = *aptr;
13775                 if (name) {
13776                         do {
13777                                 p = strchr(name, '=');
13778                                 if (p != NULL) {
13779                                         p++;
13780                                 } else {
13781                                         vp = *findvar(hashvar(name), name);
13782                                         if (vp) {
13783                                                 vp->flags = ((vp->flags | flag) & flag_off);
13784                                                 continue;
13785                                         }
13786                                 }
13787                                 setvar(name, p, (flag & flag_off));
13788                         } while ((name = *++aptr) != NULL);
13789                         return 0;
13790                 }
13791         }
13792
13793         /* No arguments. Show the list of exported or readonly vars.
13794          * -n is ignored.
13795          */
13796         showvars(argv[0], flag, 0);
13797         return 0;
13798 }
13799
13800 /*
13801  * Delete a function if it exists.
13802  */
13803 static void
13804 unsetfunc(const char *name)
13805 {
13806         struct tblentry *cmdp;
13807
13808         cmdp = cmdlookup(name, 0);
13809         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13810                 delete_cmd_entry();
13811 }
13812
13813 /*
13814  * The unset builtin command.  We unset the function before we unset the
13815  * variable to allow a function to be unset when there is a readonly variable
13816  * with the same name.
13817  */
13818 static int FAST_FUNC
13819 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13820 {
13821         char **ap;
13822         int i;
13823         int flag = 0;
13824
13825         while ((i = nextopt("vf")) != 0) {
13826                 flag = i;
13827         }
13828
13829         for (ap = argptr; *ap; ap++) {
13830                 if (flag != 'f') {
13831                         unsetvar(*ap);
13832                         continue;
13833                 }
13834                 if (flag != 'v')
13835                         unsetfunc(*ap);
13836         }
13837         return 0;
13838 }
13839
13840 static const unsigned char timescmd_str[] ALIGN1 = {
13841         ' ',  offsetof(struct tms, tms_utime),
13842         '\n', offsetof(struct tms, tms_stime),
13843         ' ',  offsetof(struct tms, tms_cutime),
13844         '\n', offsetof(struct tms, tms_cstime),
13845         0
13846 };
13847 static int FAST_FUNC
13848 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13849 {
13850         unsigned clk_tck;
13851         const unsigned char *p;
13852         struct tms buf;
13853
13854         clk_tck = bb_clk_tck();
13855
13856         times(&buf);
13857         p = timescmd_str;
13858         do {
13859                 unsigned sec, frac;
13860                 unsigned long t;
13861                 t = *(clock_t *)(((char *) &buf) + p[1]);
13862                 sec = t / clk_tck;
13863                 frac = t % clk_tck;
13864                 out1fmt("%um%u.%03us%c",
13865                         sec / 60, sec % 60,
13866                         (frac * 1000) / clk_tck,
13867                         p[0]);
13868                 p += 2;
13869         } while (*p);
13870
13871         return 0;
13872 }
13873
13874 #if ENABLE_FEATURE_SH_MATH
13875 /*
13876  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13877  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13878  *
13879  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13880  */
13881 static int FAST_FUNC
13882 letcmd(int argc UNUSED_PARAM, char **argv)
13883 {
13884         arith_t i;
13885
13886         argv++;
13887         if (!*argv)
13888                 ash_msg_and_raise_error("expression expected");
13889         do {
13890                 i = ash_arith(*argv);
13891         } while (*++argv);
13892
13893         return !i;
13894 }
13895 #endif
13896
13897 /*
13898  * The read builtin. Options:
13899  *      -r              Do not interpret '\' specially
13900  *      -s              Turn off echo (tty only)
13901  *      -n NCHARS       Read NCHARS max
13902  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13903  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13904  *      -u FD           Read from given FD instead of fd 0
13905  *      -d DELIM        End on DELIM char, not newline
13906  * This uses unbuffered input, which may be avoidable in some cases.
13907  * TODO: bash also has:
13908  *      -a ARRAY        Read into array[0],[1],etc
13909  *      -e              Use line editing (tty only)
13910  */
13911 static int FAST_FUNC
13912 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13913 {
13914         struct builtin_read_params params;
13915         const char *r;
13916         int i;
13917
13918         memset(&params, 0, sizeof(params));
13919
13920         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13921                 switch (i) {
13922                 case 'p':
13923                         params.opt_p = optionarg;
13924                         break;
13925                 case 'n':
13926                         params.opt_n = optionarg;
13927                         break;
13928                 case 's':
13929                         params.read_flags |= BUILTIN_READ_SILENT;
13930                         break;
13931                 case 't':
13932                         params.opt_t = optionarg;
13933                         break;
13934                 case 'r':
13935                         params.read_flags |= BUILTIN_READ_RAW;
13936                         break;
13937                 case 'u':
13938                         params.opt_u = optionarg;
13939                         break;
13940 #if BASH_READ_D
13941                 case 'd':
13942                         params.opt_d = optionarg;
13943                         break;
13944 #endif
13945                 default:
13946                         break;
13947                 }
13948         }
13949
13950         params.argv = argptr;
13951         params.setvar = setvar0;
13952         params.ifs = bltinlookup("IFS"); /* can be NULL */
13953
13954         /* "read -s" needs to save/restore termios, can't allow ^C
13955          * to jump out of it.
13956          */
13957  again:
13958         INT_OFF;
13959         r = shell_builtin_read(&params);
13960         INT_ON;
13961
13962         if ((uintptr_t)r == 1 && errno == EINTR) {
13963                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13964                  * Correct behavior is to not exit "read"
13965                  */
13966                 if (pending_sig == 0)
13967                         goto again;
13968         }
13969
13970         if ((uintptr_t)r > 1)
13971                 ash_msg_and_raise_error(r);
13972
13973         return (uintptr_t)r;
13974 }
13975
13976 static int FAST_FUNC
13977 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13978 {
13979         static const char permuser[3] ALIGN1 = "ogu";
13980
13981         mode_t mask;
13982         int symbolic_mode = 0;
13983
13984         while (nextopt("S") != '\0') {
13985                 symbolic_mode = 1;
13986         }
13987
13988         INT_OFF;
13989         mask = umask(0);
13990         umask(mask);
13991         INT_ON;
13992
13993         if (*argptr == NULL) {
13994                 if (symbolic_mode) {
13995                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13996                         char *p = buf;
13997                         int i;
13998
13999                         i = 2;
14000                         for (;;) {
14001                                 *p++ = ',';
14002                                 *p++ = permuser[i];
14003                                 *p++ = '=';
14004                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14005                                 if (!(mask & 0400)) *p++ = 'r';
14006                                 if (!(mask & 0200)) *p++ = 'w';
14007                                 if (!(mask & 0100)) *p++ = 'x';
14008                                 mask <<= 3;
14009                                 if (--i < 0)
14010                                         break;
14011                         }
14012                         *p = '\0';
14013                         puts(buf + 1);
14014                 } else {
14015                         out1fmt("%04o\n", mask);
14016                 }
14017         } else {
14018                 char *modestr = *argptr;
14019                 /* numeric umasks are taken as-is */
14020                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14021                 if (!isdigit(modestr[0]))
14022                         mask ^= 0777;
14023                 mask = bb_parse_mode(modestr, mask);
14024                 if ((unsigned)mask > 0777) {
14025                         ash_msg_and_raise_error("illegal mode: %s", modestr);
14026                 }
14027                 if (!isdigit(modestr[0]))
14028                         mask ^= 0777;
14029                 umask(mask);
14030         }
14031         return 0;
14032 }
14033
14034 static int FAST_FUNC
14035 ulimitcmd(int argc UNUSED_PARAM, char **argv)
14036 {
14037         return shell_builtin_ulimit(argv);
14038 }
14039
14040 /* ============ main() and helpers */
14041
14042 /*
14043  * Called to exit the shell.
14044  */
14045 static void
14046 exitshell(void)
14047 {
14048         struct jmploc loc;
14049         char *p;
14050         int status;
14051
14052 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14053         if (line_input_state)
14054                 save_history(line_input_state);
14055 #endif
14056         status = exitstatus;
14057         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
14058         if (setjmp(loc.loc)) {
14059                 if (exception_type == EXEXIT)
14060                         status = exitstatus;
14061                 goto out;
14062         }
14063         exception_handler = &loc;
14064         p = trap[0];
14065         if (p) {
14066                 trap[0] = NULL;
14067                 evalskip = 0;
14068                 evalstring(p, 0);
14069                 /*free(p); - we'll exit soon */
14070         }
14071  out:
14072         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14073          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14074          */
14075         setjobctl(0);
14076         flush_stdout_stderr();
14077         _exit(status);
14078         /* NOTREACHED */
14079 }
14080
14081 /* Don't inline: conserve stack of caller from having our locals too */
14082 static NOINLINE void
14083 init(void)
14084 {
14085         /* we will never free this */
14086         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14087         basepf.linno = 1;
14088
14089         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14090         setsignal(SIGCHLD);
14091
14092         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
14093          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
14094          */
14095         signal(SIGHUP, SIG_DFL);
14096
14097         {
14098                 char **envp;
14099                 const char *p;
14100
14101                 initvar();
14102                 for (envp = environ; envp && *envp; envp++) {
14103 /* Used to have
14104  *                      p = endofname(*envp);
14105  *                      if (p != *envp && *p == '=') {
14106  * here to weed out badly-named variables, but this breaks
14107  * scenarios where people do want them passed to children:
14108  * import os
14109  * os.environ["test-test"]="test"
14110  * if os.fork() == 0:
14111  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14112  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14113  */
14114                         if (strchr(*envp, '=')) {
14115                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
14116                         }
14117                 }
14118
14119                 setvareq((char*)defifsvar, VTEXTFIXED);
14120                 setvareq((char*)defoptindvar, VTEXTFIXED);
14121
14122                 setvar0("PPID", utoa(getppid()));
14123 #if BASH_SHLVL_VAR
14124                 p = lookupvar("SHLVL");
14125                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14126 #endif
14127 #if BASH_HOSTNAME_VAR
14128                 if (!lookupvar("HOSTNAME")) {
14129                         struct utsname uts;
14130                         uname(&uts);
14131                         setvar0("HOSTNAME", uts.nodename);
14132                 }
14133 #endif
14134                 p = lookupvar("PWD");
14135                 if (p) {
14136                         struct stat st1, st2;
14137                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14138                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14139                         ) {
14140                                 p = NULL;
14141                         }
14142                 }
14143                 setpwd(p, 0);
14144         }
14145 }
14146
14147
14148 //usage:#define ash_trivial_usage
14149 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14150 //usage:#define ash_full_usage "\n\n"
14151 //usage:        "Unix shell interpreter"
14152
14153 /*
14154  * Process the shell command line arguments.
14155  */
14156 static int
14157 procargs(char **argv)
14158 {
14159         int i;
14160         const char *xminusc;
14161         char **xargv;
14162         int login_sh;
14163
14164         xargv = argv;
14165         login_sh = xargv[0] && xargv[0][0] == '-';
14166 #if NUM_SCRIPTS > 0
14167         if (minusc)
14168                 goto setarg0;
14169 #endif
14170         arg0 = xargv[0];
14171         /* if (xargv[0]) - mmm, this is always true! */
14172                 xargv++;
14173         argptr = xargv;
14174         for (i = 0; i < NOPTS; i++)
14175                 optlist[i] = 2;
14176         if (options(&login_sh)) {
14177                 /* it already printed err message */
14178                 raise_exception(EXERROR);
14179         }
14180         xargv = argptr;
14181         xminusc = minusc;
14182         if (*xargv == NULL) {
14183                 if (xminusc)
14184                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14185                 sflag = 1;
14186         }
14187         if (iflag == 2 /* no explicit -i given */
14188          && sflag == 1 /* -s given (or implied) */
14189          && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14190          && isatty(0) && isatty(1) /* we are on tty */
14191         ) {
14192                 iflag = 1;
14193         }
14194         if (mflag == 2)
14195                 mflag = iflag;
14196         for (i = 0; i < NOPTS; i++)
14197                 if (optlist[i] == 2)
14198                         optlist[i] = 0;
14199 #if DEBUG == 2
14200         debug = 1;
14201 #endif
14202         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14203         if (xminusc) {
14204                 minusc = *xargv++;
14205                 if (*xargv)
14206                         goto setarg0;
14207         } else if (!sflag) {
14208                 setinputfile(*xargv, 0);
14209  setarg0:
14210                 arg0 = *xargv++;
14211                 commandname = arg0;
14212         }
14213
14214         shellparam.p = xargv;
14215 #if ENABLE_ASH_GETOPTS
14216         shellparam.optind = 1;
14217         shellparam.optoff = -1;
14218 #endif
14219         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14220         while (*xargv) {
14221                 shellparam.nparam++;
14222                 xargv++;
14223         }
14224         optschanged();
14225
14226         return login_sh;
14227 }
14228
14229 /*
14230  * Read /etc/profile, ~/.profile, $ENV.
14231  */
14232 static void
14233 read_profile(const char *name)
14234 {
14235         name = expandstr(name, DQSYNTAX);
14236         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14237                 return;
14238         cmdloop(0);
14239         popfile();
14240 }
14241
14242 /*
14243  * This routine is called when an error or an interrupt occurs in an
14244  * interactive shell and control is returned to the main command loop.
14245  * (In dash, this function is auto-generated by build machinery).
14246  */
14247 static void
14248 reset(void)
14249 {
14250         /* from eval.c: */
14251         evalskip = 0;
14252         loopnest = 0;
14253
14254         /* from expand.c: */
14255         ifsfree();
14256
14257         /* from input.c: */
14258         g_parsefile->left_in_buffer = 0;
14259         g_parsefile->left_in_line = 0;      /* clear input buffer */
14260         popallfiles();
14261
14262         /* from redir.c: */
14263         unwindredir(NULL);
14264
14265         /* from var.c: */
14266         unwindlocalvars(NULL);
14267 }
14268
14269 #if PROFILE
14270 static short profile_buf[16384];
14271 extern int etext();
14272 #endif
14273
14274 /*
14275  * Main routine.  We initialize things, parse the arguments, execute
14276  * profiles if we're a login shell, and then call cmdloop to execute
14277  * commands.  The setjmp call sets up the location to jump to when an
14278  * exception occurs.  When an exception occurs the variable "state"
14279  * is used to figure out how far we had gotten.
14280  */
14281 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14282 #if NUM_SCRIPTS > 0
14283 int ash_main(int argc, char **argv)
14284 #else
14285 int ash_main(int argc UNUSED_PARAM, char **argv)
14286 #endif
14287 /* note: 'argc' is used only if embedded scripts are enabled */
14288 {
14289         volatile smallint state;
14290         struct jmploc jmploc;
14291         struct stackmark smark;
14292         int login_sh;
14293
14294         /* Initialize global data */
14295         INIT_G_misc();
14296         INIT_G_memstack();
14297         INIT_G_var();
14298 #if ENABLE_ASH_ALIAS
14299         INIT_G_alias();
14300 #endif
14301         INIT_G_cmdtable();
14302
14303 #if PROFILE
14304         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14305 #endif
14306
14307         state = 0;
14308         if (setjmp(jmploc.loc)) {
14309                 smallint e;
14310                 smallint s;
14311
14312                 reset();
14313
14314                 e = exception_type;
14315                 s = state;
14316                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14317                         exitshell();
14318                 }
14319                 if (e == EXINT) {
14320                         newline_and_flush(stderr);
14321                 }
14322
14323                 popstackmark(&smark);
14324                 FORCE_INT_ON; /* enable interrupts */
14325                 if (s == 1)
14326                         goto state1;
14327                 if (s == 2)
14328                         goto state2;
14329                 if (s == 3)
14330                         goto state3;
14331                 goto state4;
14332         }
14333         exception_handler = &jmploc;
14334         rootpid = getpid();
14335
14336         init();
14337         setstackmark(&smark);
14338
14339 #if NUM_SCRIPTS > 0
14340         if (argc < 0)
14341                 /* Non-NULL minusc tells procargs that an embedded script is being run */
14342                 minusc = get_script_content(-argc - 1);
14343 #endif
14344         login_sh = procargs(argv);
14345 #if DEBUG
14346         TRACE(("Shell args: "));
14347         trace_puts_args(argv);
14348 #endif
14349
14350         if (login_sh) {
14351                 const char *hp;
14352
14353                 state = 1;
14354                 read_profile("/etc/profile");
14355  state1:
14356                 state = 2;
14357                 hp = lookupvar("HOME");
14358                 if (hp)
14359                         read_profile("$HOME/.profile");
14360         }
14361  state2:
14362         state = 3;
14363         if (
14364 #ifndef linux
14365          getuid() == geteuid() && getgid() == getegid() &&
14366 #endif
14367          iflag
14368         ) {
14369                 const char *shinit = lookupvar("ENV");
14370                 if (shinit != NULL && *shinit != '\0')
14371                         read_profile(shinit);
14372         }
14373         popstackmark(&smark);
14374  state3:
14375         state = 4;
14376         if (minusc) {
14377                 /* evalstring pushes parsefile stack.
14378                  * Ensure we don't falsely claim that 0 (stdin)
14379                  * is one of stacked source fds.
14380                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14381
14382                 // if (!sflag) g_parsefile->pf_fd = -1;
14383                 // ^^ not necessary since now we special-case fd 0
14384                 // in save_fd_on_redirect()
14385
14386                 // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14387                 // The above makes
14388                 //  ash -sc 'echo $-'
14389                 // continue reading input from stdin after running 'echo'.
14390                 // bash does not do this: it prints "hBcs" and exits.
14391                 evalstring(minusc, EV_EXIT);
14392         }
14393
14394         if (sflag || minusc == NULL) {
14395 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14396                 if (iflag) {
14397                         const char *hp = lookupvar("HISTFILE");
14398                         if (!hp) {
14399                                 hp = lookupvar("HOME");
14400                                 if (hp) {
14401                                         INT_OFF;
14402                                         hp = concat_path_file(hp, ".ash_history");
14403                                         setvar0("HISTFILE", hp);
14404                                         free((char*)hp);
14405                                         INT_ON;
14406                                         hp = lookupvar("HISTFILE");
14407                                 }
14408                         }
14409                         if (hp)
14410                                 line_input_state->hist_file = hp;
14411 # if ENABLE_FEATURE_SH_HISTFILESIZE
14412                         hp = lookupvar("HISTFILESIZE");
14413                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14414 # endif
14415                 }
14416 #endif
14417  state4: /* XXX ??? - why isn't this before the "if" statement */
14418                 cmdloop(1);
14419         }
14420 #if PROFILE
14421         monitor(0);
14422 #endif
14423 #ifdef GPROF
14424         {
14425                 extern void _mcleanup(void);
14426                 _mcleanup();
14427         }
14428 #endif
14429         TRACE(("End of main reached\n"));
14430         exitshell();
14431         /* NOTREACHED */
14432 }
14433
14434
14435 /*-
14436  * Copyright (c) 1989, 1991, 1993, 1994
14437  *      The Regents of the University of California.  All rights reserved.
14438  *
14439  * This code is derived from software contributed to Berkeley by
14440  * Kenneth Almquist.
14441  *
14442  * Redistribution and use in source and binary forms, with or without
14443  * modification, are permitted provided that the following conditions
14444  * are met:
14445  * 1. Redistributions of source code must retain the above copyright
14446  *    notice, this list of conditions and the following disclaimer.
14447  * 2. Redistributions in binary form must reproduce the above copyright
14448  *    notice, this list of conditions and the following disclaimer in the
14449  *    documentation and/or other materials provided with the distribution.
14450  * 3. Neither the name of the University nor the names of its contributors
14451  *    may be used to endorse or promote products derived from this software
14452  *    without specific prior written permission.
14453  *
14454  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14455  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14456  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14457  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14458  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14459  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14460  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14461  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14462  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14463  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14464  * SUCH DAMAGE.
14465  */