35ea58f3aa361976cce76a7dadd0742db5dbb3dc
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_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 <setjmp.h>
181 #include <fnmatch.h>
182 #include <sys/times.h>
183 #include <sys/utsname.h> /* for setting $HOSTNAME */
184 #include "busybox.h" /* for applet_names */
185
186 /* So far, all bash compat is controlled by one config option */
187 /* Separate defines document which part of code implements what */
188 /* function keyword */
189 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
190 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
191 /* &>file */
192 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
194 /* $'...' */
195 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
196 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
197 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
198 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
199 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
201 /* [[ EXPR ]] */
202 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
203 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
204 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
205 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
206 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
207 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
208 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
209 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
210
211 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
212 /* Bionic at least up to version 24 has no glob() */
213 # undef  ENABLE_ASH_INTERNAL_GLOB
214 # define ENABLE_ASH_INTERNAL_GLOB 1
215 #endif
216
217 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
218 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
219 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
220 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
221 # error glob() should unbackslash them and match. uClibc does not unbackslash,
222 # error fails to match dirname, subsequently not expanding <pattern> in it.
223 // Testcase:
224 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
225 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
226 #endif
227
228 #if !ENABLE_ASH_INTERNAL_GLOB
229 # include <glob.h>
230 #endif
231
232 #include "unicode.h"
233 #include "shell_common.h"
234 #if ENABLE_FEATURE_SH_MATH
235 # include "math.h"
236 #else
237 typedef long arith_t;
238 # define ARITH_FMT "%ld"
239 #endif
240 #if ENABLE_ASH_RANDOM_SUPPORT
241 # include "random.h"
242 #else
243 # define CLEAR_RANDOM_T(rnd) ((void)0)
244 #endif
245
246 #include "NUM_APPLETS.h"
247 #if NUM_APPLETS == 1
248 /* STANDALONE does not make sense, and won't compile */
249 # undef CONFIG_FEATURE_SH_STANDALONE
250 # undef ENABLE_FEATURE_SH_STANDALONE
251 # undef IF_FEATURE_SH_STANDALONE
252 # undef IF_NOT_FEATURE_SH_STANDALONE
253 # define ENABLE_FEATURE_SH_STANDALONE 0
254 # define IF_FEATURE_SH_STANDALONE(...)
255 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
256 #endif
257
258 #ifndef F_DUPFD_CLOEXEC
259 # define F_DUPFD_CLOEXEC F_DUPFD
260 #endif
261 #ifndef O_CLOEXEC
262 # define O_CLOEXEC 0
263 #endif
264 #ifndef PIPE_BUF
265 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
266 #endif
267
268 #if !BB_MMU
269 # error "Do not even bother, ash will not run on NOMMU machine"
270 #endif
271
272 /* We use a trick to have more optimized code (fewer pointer reloads):
273  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
274  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
275  * This way, compiler in ash.c knows the pointer can not change.
276  *
277  * However, this may break on weird arches or toolchains. In this case,
278  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
279  * this optimization.
280  */
281 #ifndef BB_GLOBAL_CONST
282 # define BB_GLOBAL_CONST const
283 #endif
284
285
286 /* ============ Hash table sizes. Configurable. */
287
288 #define VTABSIZE 39
289 #define ATABSIZE 39
290 #define CMDTABLESIZE 31         /* should be prime */
291
292
293 /* ============ Shell options */
294
295 static const char *const optletters_optnames[] = {
296         "e"   "errexit",
297         "f"   "noglob",
298         "I"   "ignoreeof",
299         "i"   "interactive",
300         "m"   "monitor",
301         "n"   "noexec",
302         "s"   "stdin",
303         "x"   "xtrace",
304         "v"   "verbose",
305         "C"   "noclobber",
306         "a"   "allexport",
307         "b"   "notify",
308         "u"   "nounset",
309         "\0"  "vi"
310 #if BASH_PIPEFAIL
311         ,"\0"  "pipefail"
312 #endif
313 #if DEBUG
314         ,"\0"  "nolog"
315         ,"\0"  "debug"
316 #endif
317 };
318
319 #define optletters(n)  optletters_optnames[n][0]
320 #define optnames(n)   (optletters_optnames[n] + 1)
321
322 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
323
324
325 /* ============ Misc data */
326
327 #define msg_illnum "Illegal number: %s"
328
329 /*
330  * We enclose jmp_buf in a structure so that we can declare pointers to
331  * jump locations.  The global variable handler contains the location to
332  * jump to when an exception occurs, and the global variable exception_type
333  * contains a code identifying the exception.  To implement nested
334  * exception handlers, the user should save the value of handler on entry
335  * to an inner scope, set handler to point to a jmploc structure for the
336  * inner scope, and restore handler on exit from the scope.
337  */
338 struct jmploc {
339         jmp_buf loc;
340 };
341
342 struct globals_misc {
343         uint8_t exitstatus;     /* exit status of last command */
344         uint8_t back_exitstatus;/* exit status of backquoted command */
345         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
346         int rootpid;            /* pid of main shell */
347         /* shell level: 0 for the main shell, 1 for its children, and so on */
348         int shlvl;
349 #define rootshell (!shlvl)
350         int errlinno;
351
352         char *minusc;  /* argument to -c option */
353
354         char *curdir; // = nullstr;     /* current working directory */
355         char *physdir; // = nullstr;    /* physical working directory */
356
357         char *arg0; /* value of $0 */
358
359         struct jmploc *exception_handler;
360
361         volatile int suppress_int; /* counter */
362         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
363         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
364         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
365         smallint exception_type; /* kind of exception (0..5) */
366         /* exceptions */
367 #define EXINT 0         /* SIGINT received */
368 #define EXERROR 1       /* a generic error */
369 #define EXEXIT 4        /* exit the shell */
370
371         char nullstr[1];        /* zero length string */
372
373         char optlist[NOPTS];
374 #define eflag optlist[0]
375 #define fflag optlist[1]
376 #define Iflag optlist[2]
377 #define iflag optlist[3]
378 #define mflag optlist[4]
379 #define nflag optlist[5]
380 #define sflag optlist[6]
381 #define xflag optlist[7]
382 #define vflag optlist[8]
383 #define Cflag optlist[9]
384 #define aflag optlist[10]
385 #define bflag optlist[11]
386 #define uflag optlist[12]
387 #define viflag optlist[13]
388 #if BASH_PIPEFAIL
389 # define pipefail optlist[14]
390 #else
391 # define pipefail 0
392 #endif
393 #if DEBUG
394 # define nolog optlist[14 + BASH_PIPEFAIL]
395 # define debug optlist[15 + BASH_PIPEFAIL]
396 #endif
397
398         /* trap handler commands */
399         /*
400          * Sigmode records the current value of the signal handlers for the various
401          * modes.  A value of zero means that the current handler is not known.
402          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
403          */
404         char sigmode[NSIG - 1];
405 #define S_DFL      1            /* default signal handling (SIG_DFL) */
406 #define S_CATCH    2            /* signal is caught */
407 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
408 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
409
410         /* indicates specified signal received */
411         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
412         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
413         char *trap[NSIG];
414         char **trap_ptr;        /* used only by "trap hack" */
415
416         /* Rarely referenced stuff */
417 #if ENABLE_ASH_RANDOM_SUPPORT
418         random_t random_gen;
419 #endif
420         pid_t backgndpid;        /* pid of last background process */
421 };
422 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
423 #define G_misc (*ash_ptr_to_globals_misc)
424 #define exitstatus        (G_misc.exitstatus )
425 #define back_exitstatus   (G_misc.back_exitstatus )
426 #define job_warning       (G_misc.job_warning)
427 #define rootpid     (G_misc.rootpid    )
428 #define shlvl       (G_misc.shlvl      )
429 #define errlinno    (G_misc.errlinno   )
430 #define minusc      (G_misc.minusc     )
431 #define curdir      (G_misc.curdir     )
432 #define physdir     (G_misc.physdir    )
433 #define arg0        (G_misc.arg0       )
434 #define exception_handler (G_misc.exception_handler)
435 #define exception_type    (G_misc.exception_type   )
436 #define suppress_int      (G_misc.suppress_int     )
437 #define pending_int       (G_misc.pending_int      )
438 #define got_sigchld       (G_misc.got_sigchld      )
439 #define pending_sig       (G_misc.pending_sig      )
440 #define nullstr     (G_misc.nullstr    )
441 #define optlist     (G_misc.optlist    )
442 #define sigmode     (G_misc.sigmode    )
443 #define gotsig      (G_misc.gotsig     )
444 #define may_have_traps    (G_misc.may_have_traps   )
445 #define trap        (G_misc.trap       )
446 #define trap_ptr    (G_misc.trap_ptr   )
447 #define random_gen  (G_misc.random_gen )
448 #define backgndpid  (G_misc.backgndpid )
449 #define INIT_G_misc() do { \
450         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
451         barrier(); \
452         curdir = nullstr; \
453         physdir = nullstr; \
454         trap_ptr = trap; \
455 } while (0)
456
457
458 /* ============ DEBUG */
459 #if DEBUG
460 static void trace_printf(const char *fmt, ...);
461 static void trace_vprintf(const char *fmt, va_list va);
462 # define TRACE(param)    trace_printf param
463 # define TRACEV(param)   trace_vprintf param
464 # define close(fd) do { \
465         int dfd = (fd); \
466         if (close(dfd) < 0) \
467                 bb_error_msg("bug on %d: closing %d(0x%x)", \
468                         __LINE__, dfd, dfd); \
469 } while (0)
470 #else
471 # define TRACE(param)
472 # define TRACEV(param)
473 #endif
474
475
476 /* ============ Utility functions */
477 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
478 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
479
480 static int
481 isdigit_str9(const char *str)
482 {
483         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
484         while (--maxlen && isdigit(*str))
485                 str++;
486         return (*str == '\0');
487 }
488
489 static const char *
490 var_end(const char *var)
491 {
492         while (*var)
493                 if (*var++ == '=')
494                         break;
495         return var;
496 }
497
498
499 /* ============ Interrupts / exceptions */
500
501 static void exitshell(void) NORETURN;
502
503 /*
504  * These macros allow the user to suspend the handling of interrupt signals
505  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
506  * much more efficient and portable.  (But hacking the kernel is so much
507  * more fun than worrying about efficiency and portability. :-))
508  */
509 #if DEBUG_INTONOFF
510 # define INT_OFF do { \
511         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
512         suppress_int++; \
513         barrier(); \
514 } while (0)
515 #else
516 # define INT_OFF do { \
517         suppress_int++; \
518         barrier(); \
519 } while (0)
520 #endif
521
522 /*
523  * Called to raise an exception.  Since C doesn't include exceptions, we
524  * just do a longjmp to the exception handler.  The type of exception is
525  * stored in the global variable "exception_type".
526  */
527 static void raise_exception(int) NORETURN;
528 static void
529 raise_exception(int e)
530 {
531 #if DEBUG
532         if (exception_handler == NULL)
533                 abort();
534 #endif
535         INT_OFF;
536         exception_type = e;
537         longjmp(exception_handler->loc, 1);
538 }
539 #if DEBUG
540 #define raise_exception(e) do { \
541         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
542         raise_exception(e); \
543 } while (0)
544 #endif
545
546 /*
547  * Called when a SIGINT is received.  (If the user specifies
548  * that SIGINT is to be trapped or ignored using the trap builtin, then
549  * this routine is not called.)  Suppressint is nonzero when interrupts
550  * are held using the INT_OFF macro.  (The test for iflag is just
551  * defensive programming.)
552  */
553 static void raise_interrupt(void) NORETURN;
554 static void
555 raise_interrupt(void)
556 {
557         pending_int = 0;
558         /* Signal is not automatically unmasked after it is raised,
559          * do it ourself - unmask all signals */
560         sigprocmask_allsigs(SIG_UNBLOCK);
561         /* pending_sig = 0; - now done in signal_handler() */
562
563         if (!(rootshell && iflag)) {
564                 /* Kill ourself with SIGINT */
565                 signal(SIGINT, SIG_DFL);
566                 raise(SIGINT);
567         }
568         /* bash: ^C even on empty command line sets $? */
569         exitstatus = SIGINT + 128;
570         raise_exception(EXINT);
571         /* NOTREACHED */
572 }
573 #if DEBUG
574 #define raise_interrupt() do { \
575         TRACE(("raising interrupt on line %d\n", __LINE__)); \
576         raise_interrupt(); \
577 } while (0)
578 #endif
579
580 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
581 int_on(void)
582 {
583         barrier();
584         if (--suppress_int == 0 && pending_int) {
585                 raise_interrupt();
586         }
587 }
588 #if DEBUG_INTONOFF
589 # define INT_ON do { \
590         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
591         int_on(); \
592 } while (0)
593 #else
594 # define INT_ON int_on()
595 #endif
596 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
597 force_int_on(void)
598 {
599         barrier();
600         suppress_int = 0;
601         if (pending_int)
602                 raise_interrupt();
603 }
604 #define FORCE_INT_ON force_int_on()
605
606 #define SAVE_INT(v) ((v) = suppress_int)
607
608 #define RESTORE_INT(v) do { \
609         barrier(); \
610         suppress_int = (v); \
611         if (suppress_int == 0 && pending_int) \
612                 raise_interrupt(); \
613 } while (0)
614
615
616 /* ============ Stdout/stderr output */
617
618 static void
619 outstr(const char *p, FILE *file)
620 {
621         INT_OFF;
622         fputs(p, file);
623         INT_ON;
624 }
625
626 static void
627 flush_stdout_stderr(void)
628 {
629         INT_OFF;
630         fflush_all();
631         INT_ON;
632 }
633
634 /* Was called outcslow(c,FILE*), but c was always '\n' */
635 static void
636 newline_and_flush(FILE *dest)
637 {
638         INT_OFF;
639         putc('\n', dest);
640         fflush(dest);
641         INT_ON;
642 }
643
644 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
645 static int
646 out1fmt(const char *fmt, ...)
647 {
648         va_list ap;
649         int r;
650
651         INT_OFF;
652         va_start(ap, fmt);
653         r = vprintf(fmt, ap);
654         va_end(ap);
655         INT_ON;
656         return r;
657 }
658
659 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
660 static int
661 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
662 {
663         va_list ap;
664         int ret;
665
666         INT_OFF;
667         va_start(ap, fmt);
668         ret = vsnprintf(outbuf, length, fmt, ap);
669         va_end(ap);
670         INT_ON;
671         return ret;
672 }
673
674 static void
675 out1str(const char *p)
676 {
677         outstr(p, stdout);
678 }
679
680 static void
681 out2str(const char *p)
682 {
683         outstr(p, stderr);
684         flush_stdout_stderr();
685 }
686
687
688 /* ============ Parser structures */
689
690 /* control characters in argument strings */
691 #define CTL_FIRST CTLESC
692 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
693 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
694 #define CTLENDVAR    ((unsigned char)'\203')
695 #define CTLBACKQ     ((unsigned char)'\204')
696 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
697 #define CTLENDARI    ((unsigned char)'\207')
698 #define CTLQUOTEMARK ((unsigned char)'\210')
699 #define CTL_LAST CTLQUOTEMARK
700
701 /* variable substitution byte (follows CTLVAR) */
702 #define VSTYPE  0x0f            /* type of variable substitution */
703 #define VSNUL   0x10            /* colon--treat the empty string as unset */
704
705 /* values of VSTYPE field */
706 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
707 #define VSMINUS         0x2     /* ${var-text} */
708 #define VSPLUS          0x3     /* ${var+text} */
709 #define VSQUESTION      0x4     /* ${var?message} */
710 #define VSASSIGN        0x5     /* ${var=text} */
711 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
712 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
713 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
714 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
715 #define VSLENGTH        0xa     /* ${#var} */
716 #if BASH_SUBSTR
717 #define VSSUBSTR        0xc     /* ${var:position:length} */
718 #endif
719 #if BASH_PATTERN_SUBST
720 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
721 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
722 #endif
723
724 static const char dolatstr[] ALIGN1 = {
725         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
726 };
727 #define DOLATSTRLEN 6
728
729 #define NCMD      0
730 #define NPIPE     1
731 #define NREDIR    2
732 #define NBACKGND  3
733 #define NSUBSHELL 4
734 #define NAND      5
735 #define NOR       6
736 #define NSEMI     7
737 #define NIF       8
738 #define NWHILE    9
739 #define NUNTIL   10
740 #define NFOR     11
741 #define NCASE    12
742 #define NCLIST   13
743 #define NDEFUN   14
744 #define NARG     15
745 #define NTO      16
746 #if BASH_REDIR_OUTPUT
747 #define NTO2     17
748 #endif
749 #define NCLOBBER 18
750 #define NFROM    19
751 #define NFROMTO  20
752 #define NAPPEND  21
753 #define NTOFD    22
754 #define NFROMFD  23
755 #define NHERE    24
756 #define NXHERE   25
757 #define NNOT     26
758 #define N_NUMBER 27
759
760 union node;
761
762 struct ncmd {
763         smallint type; /* Nxxxx */
764         int linno;
765         union node *assign;
766         union node *args;
767         union node *redirect;
768 };
769
770 struct npipe {
771         smallint type;
772         smallint pipe_backgnd;
773         struct nodelist *cmdlist;
774 };
775
776 struct nredir {
777         smallint type;
778         int linno;
779         union node *n;
780         union node *redirect;
781 };
782
783 struct nbinary {
784         smallint type;
785         union node *ch1;
786         union node *ch2;
787 };
788
789 struct nif {
790         smallint type;
791         union node *test;
792         union node *ifpart;
793         union node *elsepart;
794 };
795
796 struct nfor {
797         smallint type;
798         int linno;
799         union node *args;
800         union node *body;
801         char *var;
802 };
803
804 struct ncase {
805         smallint type;
806         int linno;
807         union node *expr;
808         union node *cases;
809 };
810
811 struct nclist {
812         smallint type;
813         union node *next;
814         union node *pattern;
815         union node *body;
816 };
817
818 struct ndefun {
819         smallint type;
820         int linno;
821         char *text;
822         union node *body;
823 };
824
825 struct narg {
826         smallint type;
827         union node *next;
828         char *text;
829         struct nodelist *backquote;
830 };
831
832 /* nfile and ndup layout must match!
833  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
834  * that it is actually NTO2 (>&file), and change its type.
835  */
836 struct nfile {
837         smallint type;
838         union node *next;
839         int fd;
840         int _unused_dupfd;
841         union node *fname;
842         char *expfname;
843 };
844
845 struct ndup {
846         smallint type;
847         union node *next;
848         int fd;
849         int dupfd;
850         union node *vname;
851         char *_unused_expfname;
852 };
853
854 struct nhere {
855         smallint type;
856         union node *next;
857         int fd;
858         union node *doc;
859 };
860
861 struct nnot {
862         smallint type;
863         union node *com;
864 };
865
866 union node {
867         smallint type;
868         struct ncmd ncmd;
869         struct npipe npipe;
870         struct nredir nredir;
871         struct nbinary nbinary;
872         struct nif nif;
873         struct nfor nfor;
874         struct ncase ncase;
875         struct nclist nclist;
876         struct ndefun ndefun;
877         struct narg narg;
878         struct nfile nfile;
879         struct ndup ndup;
880         struct nhere nhere;
881         struct nnot nnot;
882 };
883
884 /*
885  * NODE_EOF is returned by parsecmd when it encounters an end of file.
886  * It must be distinct from NULL.
887  */
888 #define NODE_EOF ((union node *) -1L)
889
890 struct nodelist {
891         struct nodelist *next;
892         union node *n;
893 };
894
895 struct funcnode {
896         int count;
897         union node n;
898 };
899
900 /*
901  * Free a parse tree.
902  */
903 static void
904 freefunc(struct funcnode *f)
905 {
906         if (f && --f->count < 0)
907                 free(f);
908 }
909
910
911 /* ============ Debugging output */
912
913 #if DEBUG
914
915 static FILE *tracefile;
916
917 static void
918 trace_printf(const char *fmt, ...)
919 {
920         va_list va;
921
922         if (debug != 1)
923                 return;
924         if (DEBUG_TIME)
925                 fprintf(tracefile, "%u ", (int) time(NULL));
926         if (DEBUG_PID)
927                 fprintf(tracefile, "[%u] ", (int) getpid());
928         if (DEBUG_SIG)
929                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
930         va_start(va, fmt);
931         vfprintf(tracefile, fmt, va);
932         va_end(va);
933 }
934
935 static void
936 trace_vprintf(const char *fmt, va_list va)
937 {
938         if (debug != 1)
939                 return;
940         vfprintf(tracefile, fmt, va);
941         fprintf(tracefile, "\n");
942 }
943
944 static void
945 trace_puts(const char *s)
946 {
947         if (debug != 1)
948                 return;
949         fputs(s, tracefile);
950 }
951
952 static void
953 trace_puts_quoted(char *s)
954 {
955         char *p;
956         char c;
957
958         if (debug != 1)
959                 return;
960         putc('"', tracefile);
961         for (p = s; *p; p++) {
962                 switch ((unsigned char)*p) {
963                 case '\n': c = 'n'; goto backslash;
964                 case '\t': c = 't'; goto backslash;
965                 case '\r': c = 'r'; goto backslash;
966                 case '\"': c = '\"'; goto backslash;
967                 case '\\': c = '\\'; goto backslash;
968                 case CTLESC: c = 'e'; goto backslash;
969                 case CTLVAR: c = 'v'; goto backslash;
970                 case CTLBACKQ: c = 'q'; goto backslash;
971  backslash:
972                         putc('\\', tracefile);
973                         putc(c, tracefile);
974                         break;
975                 default:
976                         if (*p >= ' ' && *p <= '~')
977                                 putc(*p, tracefile);
978                         else {
979                                 putc('\\', tracefile);
980                                 putc((*p >> 6) & 03, tracefile);
981                                 putc((*p >> 3) & 07, tracefile);
982                                 putc(*p & 07, tracefile);
983                         }
984                         break;
985                 }
986         }
987         putc('"', tracefile);
988 }
989
990 static void
991 trace_puts_args(char **ap)
992 {
993         if (debug != 1)
994                 return;
995         if (!*ap)
996                 return;
997         while (1) {
998                 trace_puts_quoted(*ap);
999                 if (!*++ap) {
1000                         putc('\n', tracefile);
1001                         break;
1002                 }
1003                 putc(' ', tracefile);
1004         }
1005 }
1006
1007 static void
1008 opentrace(void)
1009 {
1010         char s[100];
1011 #ifdef O_APPEND
1012         int flags;
1013 #endif
1014
1015         if (debug != 1) {
1016                 if (tracefile)
1017                         fflush(tracefile);
1018                 /* leave open because libedit might be using it */
1019                 return;
1020         }
1021         strcpy(s, "./trace");
1022         if (tracefile) {
1023                 if (!freopen(s, "a", tracefile)) {
1024                         fprintf(stderr, "Can't re-open %s\n", s);
1025                         debug = 0;
1026                         return;
1027                 }
1028         } else {
1029                 tracefile = fopen(s, "a");
1030                 if (tracefile == NULL) {
1031                         fprintf(stderr, "Can't open %s\n", s);
1032                         debug = 0;
1033                         return;
1034                 }
1035         }
1036 #ifdef O_APPEND
1037         flags = fcntl(fileno(tracefile), F_GETFL);
1038         if (flags >= 0)
1039                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1040 #endif
1041         setlinebuf(tracefile);
1042         fputs("\nTracing started.\n", tracefile);
1043 }
1044
1045 static void
1046 indent(int amount, char *pfx, FILE *fp)
1047 {
1048         int i;
1049
1050         for (i = 0; i < amount; i++) {
1051                 if (pfx && i == amount - 1)
1052                         fputs(pfx, fp);
1053                 putc('\t', fp);
1054         }
1055 }
1056
1057 /* little circular references here... */
1058 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1059
1060 static void
1061 sharg(union node *arg, FILE *fp)
1062 {
1063         char *p;
1064         struct nodelist *bqlist;
1065         unsigned char subtype;
1066
1067         if (arg->type != NARG) {
1068                 out1fmt("<node type %d>\n", arg->type);
1069                 abort();
1070         }
1071         bqlist = arg->narg.backquote;
1072         for (p = arg->narg.text; *p; p++) {
1073                 switch ((unsigned char)*p) {
1074                 case CTLESC:
1075                         p++;
1076                         putc(*p, fp);
1077                         break;
1078                 case CTLVAR:
1079                         putc('$', fp);
1080                         putc('{', fp);
1081                         subtype = *++p;
1082                         if (subtype == VSLENGTH)
1083                                 putc('#', fp);
1084
1085                         while (*p != '=') {
1086                                 putc(*p, fp);
1087                                 p++;
1088                         }
1089
1090                         if (subtype & VSNUL)
1091                                 putc(':', fp);
1092
1093                         switch (subtype & VSTYPE) {
1094                         case VSNORMAL:
1095                                 putc('}', fp);
1096                                 break;
1097                         case VSMINUS:
1098                                 putc('-', fp);
1099                                 break;
1100                         case VSPLUS:
1101                                 putc('+', fp);
1102                                 break;
1103                         case VSQUESTION:
1104                                 putc('?', fp);
1105                                 break;
1106                         case VSASSIGN:
1107                                 putc('=', fp);
1108                                 break;
1109                         case VSTRIMLEFT:
1110                                 putc('#', fp);
1111                                 break;
1112                         case VSTRIMLEFTMAX:
1113                                 putc('#', fp);
1114                                 putc('#', fp);
1115                                 break;
1116                         case VSTRIMRIGHT:
1117                                 putc('%', fp);
1118                                 break;
1119                         case VSTRIMRIGHTMAX:
1120                                 putc('%', fp);
1121                                 putc('%', fp);
1122                                 break;
1123                         case VSLENGTH:
1124                                 break;
1125                         default:
1126                                 out1fmt("<subtype %d>", subtype);
1127                         }
1128                         break;
1129                 case CTLENDVAR:
1130                         putc('}', fp);
1131                         break;
1132                 case CTLBACKQ:
1133                         putc('$', fp);
1134                         putc('(', fp);
1135                         shtree(bqlist->n, -1, NULL, fp);
1136                         putc(')', fp);
1137                         break;
1138                 default:
1139                         putc(*p, fp);
1140                         break;
1141                 }
1142         }
1143 }
1144
1145 static void
1146 shcmd(union node *cmd, FILE *fp)
1147 {
1148         union node *np;
1149         int first;
1150         const char *s;
1151         int dftfd;
1152
1153         first = 1;
1154         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1155                 if (!first)
1156                         putc(' ', fp);
1157                 sharg(np, fp);
1158                 first = 0;
1159         }
1160         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1161                 if (!first)
1162                         putc(' ', fp);
1163                 dftfd = 0;
1164                 switch (np->nfile.type) {
1165                 case NTO:      s = ">>"+1; dftfd = 1; break;
1166                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1167                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1168 #if BASH_REDIR_OUTPUT
1169                 case NTO2:
1170 #endif
1171                 case NTOFD:    s = ">&"; dftfd = 1; break;
1172                 case NFROM:    s = "<"; break;
1173                 case NFROMFD:  s = "<&"; break;
1174                 case NFROMTO:  s = "<>"; break;
1175                 default:       s = "*error*"; break;
1176                 }
1177                 if (np->nfile.fd != dftfd)
1178                         fprintf(fp, "%d", np->nfile.fd);
1179                 fputs(s, fp);
1180                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1181                         fprintf(fp, "%d", np->ndup.dupfd);
1182                 } else {
1183                         sharg(np->nfile.fname, fp);
1184                 }
1185                 first = 0;
1186         }
1187 }
1188
1189 static void
1190 shtree(union node *n, int ind, char *pfx, FILE *fp)
1191 {
1192         struct nodelist *lp;
1193         const char *s;
1194
1195         if (n == NULL)
1196                 return;
1197
1198         indent(ind, pfx, fp);
1199
1200         if (n == NODE_EOF) {
1201                 fputs("<EOF>", fp);
1202                 return;
1203         }
1204
1205         switch (n->type) {
1206         case NSEMI:
1207                 s = "; ";
1208                 goto binop;
1209         case NAND:
1210                 s = " && ";
1211                 goto binop;
1212         case NOR:
1213                 s = " || ";
1214  binop:
1215                 shtree(n->nbinary.ch1, ind, NULL, fp);
1216                 /* if (ind < 0) */
1217                         fputs(s, fp);
1218                 shtree(n->nbinary.ch2, ind, NULL, fp);
1219                 break;
1220         case NCMD:
1221                 shcmd(n, fp);
1222                 if (ind >= 0)
1223                         putc('\n', fp);
1224                 break;
1225         case NPIPE:
1226                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1227                         shtree(lp->n, 0, NULL, fp);
1228                         if (lp->next)
1229                                 fputs(" | ", fp);
1230                 }
1231                 if (n->npipe.pipe_backgnd)
1232                         fputs(" &", fp);
1233                 if (ind >= 0)
1234                         putc('\n', fp);
1235                 break;
1236         default:
1237                 fprintf(fp, "<node type %d>", n->type);
1238                 if (ind >= 0)
1239                         putc('\n', fp);
1240                 break;
1241         }
1242 }
1243
1244 static void
1245 showtree(union node *n)
1246 {
1247         trace_puts("showtree called\n");
1248         shtree(n, 1, NULL, stderr);
1249 }
1250
1251 #endif /* DEBUG */
1252
1253
1254 /* ============ Parser data */
1255
1256 /*
1257  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1258  */
1259 struct strlist {
1260         struct strlist *next;
1261         char *text;
1262 };
1263
1264 struct alias;
1265
1266 struct strpush {
1267         struct strpush *prev;   /* preceding string on stack */
1268         char *prev_string;
1269         int prev_left_in_line;
1270 #if ENABLE_ASH_ALIAS
1271         struct alias *ap;       /* if push was associated with an alias */
1272 #endif
1273         char *string;           /* remember the string since it may change */
1274
1275         /* Remember last two characters for pungetc. */
1276         int lastc[2];
1277
1278         /* Number of outstanding calls to pungetc. */
1279         int unget;
1280 };
1281
1282 /*
1283  * The parsefile structure pointed to by the global variable parsefile
1284  * contains information about the current file being read.
1285  */
1286 struct parsefile {
1287         struct parsefile *prev; /* preceding file on stack */
1288         int linno;              /* current line */
1289         int pf_fd;              /* file descriptor (or -1 if string) */
1290         int left_in_line;       /* number of chars left in this line */
1291         int left_in_buffer;     /* number of chars left in this buffer past the line */
1292         char *next_to_pgetc;    /* next char in buffer */
1293         char *buf;              /* input buffer */
1294         struct strpush *strpush; /* for pushing strings at this level */
1295         struct strpush basestrpush; /* so pushing one is fast */
1296
1297         /* Remember last two characters for pungetc. */
1298         int lastc[2];
1299
1300         /* Number of outstanding calls to pungetc. */
1301         int unget;
1302 };
1303
1304 static struct parsefile basepf;        /* top level input file */
1305 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1306 static char *commandname;              /* currently executing command */
1307
1308
1309 /* ============ Message printing */
1310
1311 static void
1312 ash_vmsg(const char *msg, va_list ap)
1313 {
1314         fprintf(stderr, "%s: ", arg0);
1315         if (commandname) {
1316                 if (strcmp(arg0, commandname))
1317                         fprintf(stderr, "%s: ", commandname);
1318                 if (!iflag || g_parsefile->pf_fd > 0)
1319                         fprintf(stderr, "line %d: ", errlinno);
1320         }
1321         vfprintf(stderr, msg, ap);
1322         newline_and_flush(stderr);
1323 }
1324
1325 /*
1326  * Exverror is called to raise the error exception.  If the second argument
1327  * is not NULL then error prints an error message using printf style
1328  * formatting.  It then raises the error exception.
1329  */
1330 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1331 static void
1332 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1333 {
1334 #if DEBUG
1335         if (msg) {
1336                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1337                 TRACEV((msg, ap));
1338         } else
1339                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1340         if (msg)
1341 #endif
1342                 ash_vmsg(msg, ap);
1343
1344         flush_stdout_stderr();
1345         raise_exception(cond);
1346         /* NOTREACHED */
1347 }
1348
1349 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1350 static void
1351 ash_msg_and_raise_error(const char *msg, ...)
1352 {
1353         va_list ap;
1354
1355         exitstatus = 2;
1356
1357         va_start(ap, msg);
1358         ash_vmsg_and_raise(EXERROR, msg, ap);
1359         /* NOTREACHED */
1360         va_end(ap);
1361 }
1362
1363 /*
1364  * 'fmt' must be a string literal.
1365  */
1366 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1367
1368 static void raise_error_syntax(const char *) NORETURN;
1369 static void
1370 raise_error_syntax(const char *msg)
1371 {
1372         errlinno = g_parsefile->linno;
1373         ash_msg_and_raise_error("syntax error: %s", msg);
1374         /* NOTREACHED */
1375 }
1376
1377 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1378 static void
1379 ash_msg_and_raise(int cond, const char *msg, ...)
1380 {
1381         va_list ap;
1382
1383         va_start(ap, msg);
1384         ash_vmsg_and_raise(cond, msg, ap);
1385         /* NOTREACHED */
1386         va_end(ap);
1387 }
1388
1389 /*
1390  * error/warning routines for external builtins
1391  */
1392 static void
1393 ash_msg(const char *fmt, ...)
1394 {
1395         va_list ap;
1396
1397         va_start(ap, fmt);
1398         ash_vmsg(fmt, ap);
1399         va_end(ap);
1400 }
1401
1402 /*
1403  * Return a string describing an error.  The returned string may be a
1404  * pointer to a static buffer that will be overwritten on the next call.
1405  * Action describes the operation that got the error.
1406  */
1407 static const char *
1408 errmsg(int e, const char *em)
1409 {
1410         if (e == ENOENT || e == ENOTDIR) {
1411                 return em;
1412         }
1413         return strerror(e);
1414 }
1415
1416
1417 /* ============ Memory allocation */
1418
1419 #if 0
1420 /* I consider these wrappers nearly useless:
1421  * ok, they return you to nearest exception handler, but
1422  * how much memory do you leak in the process, making
1423  * memory starvation worse?
1424  */
1425 static void *
1426 ckrealloc(void * p, size_t nbytes)
1427 {
1428         p = realloc(p, nbytes);
1429         if (!p)
1430                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1431         return p;
1432 }
1433
1434 static void *
1435 ckmalloc(size_t nbytes)
1436 {
1437         return ckrealloc(NULL, nbytes);
1438 }
1439
1440 static void *
1441 ckzalloc(size_t nbytes)
1442 {
1443         return memset(ckmalloc(nbytes), 0, nbytes);
1444 }
1445
1446 static char *
1447 ckstrdup(const char *s)
1448 {
1449         char *p = strdup(s);
1450         if (!p)
1451                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1452         return p;
1453 }
1454 #else
1455 /* Using bbox equivalents. They exit if out of memory */
1456 # define ckrealloc xrealloc
1457 # define ckmalloc  xmalloc
1458 # define ckzalloc  xzalloc
1459 # define ckstrdup  xstrdup
1460 #endif
1461
1462 /*
1463  * It appears that grabstackstr() will barf with such alignments
1464  * because stalloc() will return a string allocated in a new stackblock.
1465  */
1466 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1467 enum {
1468         /* Most machines require the value returned from malloc to be aligned
1469          * in some way.  The following macro will get this right
1470          * on many machines.  */
1471         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1472         /* Minimum size of a block */
1473         MINSIZE = SHELL_ALIGN(504),
1474 };
1475
1476 struct stack_block {
1477         struct stack_block *prev;
1478         char space[MINSIZE];
1479 };
1480
1481 struct stackmark {
1482         struct stack_block *stackp;
1483         char *stacknxt;
1484         size_t stacknleft;
1485 };
1486
1487
1488 struct globals_memstack {
1489         struct stack_block *g_stackp; // = &stackbase;
1490         char *g_stacknxt; // = stackbase.space;
1491         char *sstrend; // = stackbase.space + MINSIZE;
1492         size_t g_stacknleft; // = MINSIZE;
1493         struct stack_block stackbase;
1494 };
1495 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1496 #define G_memstack (*ash_ptr_to_globals_memstack)
1497 #define g_stackp     (G_memstack.g_stackp    )
1498 #define g_stacknxt   (G_memstack.g_stacknxt  )
1499 #define sstrend      (G_memstack.sstrend     )
1500 #define g_stacknleft (G_memstack.g_stacknleft)
1501 #define stackbase    (G_memstack.stackbase   )
1502 #define INIT_G_memstack() do { \
1503         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1504         barrier(); \
1505         g_stackp = &stackbase; \
1506         g_stacknxt = stackbase.space; \
1507         g_stacknleft = MINSIZE; \
1508         sstrend = stackbase.space + MINSIZE; \
1509 } while (0)
1510
1511
1512 #define stackblock()     ((void *)g_stacknxt)
1513 #define stackblocksize() g_stacknleft
1514
1515 /*
1516  * Parse trees for commands are allocated in lifo order, so we use a stack
1517  * to make this more efficient, and also to avoid all sorts of exception
1518  * handling code to handle interrupts in the middle of a parse.
1519  *
1520  * The size 504 was chosen because the Ultrix malloc handles that size
1521  * well.
1522  */
1523 static void *
1524 stalloc(size_t nbytes)
1525 {
1526         char *p;
1527         size_t aligned;
1528
1529         aligned = SHELL_ALIGN(nbytes);
1530         if (aligned > g_stacknleft) {
1531                 size_t len;
1532                 size_t blocksize;
1533                 struct stack_block *sp;
1534
1535                 blocksize = aligned;
1536                 if (blocksize < MINSIZE)
1537                         blocksize = MINSIZE;
1538                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1539                 if (len < blocksize)
1540                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1541                 INT_OFF;
1542                 sp = ckmalloc(len);
1543                 sp->prev = g_stackp;
1544                 g_stacknxt = sp->space;
1545                 g_stacknleft = blocksize;
1546                 sstrend = g_stacknxt + blocksize;
1547                 g_stackp = sp;
1548                 INT_ON;
1549         }
1550         p = g_stacknxt;
1551         g_stacknxt += aligned;
1552         g_stacknleft -= aligned;
1553         return p;
1554 }
1555
1556 static void *
1557 stzalloc(size_t nbytes)
1558 {
1559         return memset(stalloc(nbytes), 0, nbytes);
1560 }
1561
1562 static void
1563 stunalloc(void *p)
1564 {
1565 #if DEBUG
1566         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1567                 write(STDERR_FILENO, "stunalloc\n", 10);
1568                 abort();
1569         }
1570 #endif
1571         g_stacknleft += g_stacknxt - (char *)p;
1572         g_stacknxt = p;
1573 }
1574
1575 /*
1576  * Like strdup but works with the ash stack.
1577  */
1578 static char *
1579 sstrdup(const char *p)
1580 {
1581         size_t len = strlen(p) + 1;
1582         return memcpy(stalloc(len), p, len);
1583 }
1584
1585 static ALWAYS_INLINE void
1586 grabstackblock(size_t len)
1587 {
1588         stalloc(len);
1589 }
1590
1591 static void
1592 pushstackmark(struct stackmark *mark, size_t len)
1593 {
1594         mark->stackp = g_stackp;
1595         mark->stacknxt = g_stacknxt;
1596         mark->stacknleft = g_stacknleft;
1597         grabstackblock(len);
1598 }
1599
1600 static void
1601 setstackmark(struct stackmark *mark)
1602 {
1603         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1604 }
1605
1606 static void
1607 popstackmark(struct stackmark *mark)
1608 {
1609         struct stack_block *sp;
1610
1611         if (!mark->stackp)
1612                 return;
1613
1614         INT_OFF;
1615         while (g_stackp != mark->stackp) {
1616                 sp = g_stackp;
1617                 g_stackp = sp->prev;
1618                 free(sp);
1619         }
1620         g_stacknxt = mark->stacknxt;
1621         g_stacknleft = mark->stacknleft;
1622         sstrend = mark->stacknxt + mark->stacknleft;
1623         INT_ON;
1624 }
1625
1626 /*
1627  * When the parser reads in a string, it wants to stick the string on the
1628  * stack and only adjust the stack pointer when it knows how big the
1629  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1630  * of space on top of the stack and stackblocklen returns the length of
1631  * this block.  Growstackblock will grow this space by at least one byte,
1632  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1633  * part of the block that has been used.
1634  */
1635 static void
1636 growstackblock(void)
1637 {
1638         size_t newlen;
1639
1640         newlen = g_stacknleft * 2;
1641         if (newlen < g_stacknleft)
1642                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1643         if (newlen < 128)
1644                 newlen += 128;
1645
1646         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1647                 struct stack_block *sp;
1648                 struct stack_block *prevstackp;
1649                 size_t grosslen;
1650
1651                 INT_OFF;
1652                 sp = g_stackp;
1653                 prevstackp = sp->prev;
1654                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1655                 sp = ckrealloc(sp, grosslen);
1656                 sp->prev = prevstackp;
1657                 g_stackp = sp;
1658                 g_stacknxt = sp->space;
1659                 g_stacknleft = newlen;
1660                 sstrend = sp->space + newlen;
1661                 INT_ON;
1662         } else {
1663                 char *oldspace = g_stacknxt;
1664                 size_t oldlen = g_stacknleft;
1665                 char *p = stalloc(newlen);
1666
1667                 /* free the space we just allocated */
1668                 g_stacknxt = memcpy(p, oldspace, oldlen);
1669                 g_stacknleft += newlen;
1670         }
1671 }
1672
1673 /*
1674  * The following routines are somewhat easier to use than the above.
1675  * The user declares a variable of type STACKSTR, which may be declared
1676  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1677  * the user uses the macro STPUTC to add characters to the string.  In
1678  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1679  * grown as necessary.  When the user is done, she can just leave the
1680  * string there and refer to it using stackblock().  Or she can allocate
1681  * the space for it using grabstackstr().  If it is necessary to allow
1682  * someone else to use the stack temporarily and then continue to grow
1683  * the string, the user should use grabstack to allocate the space, and
1684  * then call ungrabstr(p) to return to the previous mode of operation.
1685  *
1686  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1687  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1688  * is space for at least one character.
1689  */
1690 static void *
1691 growstackstr(void)
1692 {
1693         size_t len = stackblocksize();
1694         growstackblock();
1695         return (char *)stackblock() + len;
1696 }
1697
1698 /*
1699  * Called from CHECKSTRSPACE.
1700  */
1701 static char *
1702 makestrspace(size_t newlen, char *p)
1703 {
1704         size_t len = p - g_stacknxt;
1705         size_t size;
1706
1707         for (;;) {
1708                 size_t nleft;
1709
1710                 size = stackblocksize();
1711                 nleft = size - len;
1712                 if (nleft >= newlen)
1713                         break;
1714                 growstackblock();
1715         }
1716         return (char *)stackblock() + len;
1717 }
1718
1719 static char *
1720 stack_nputstr(const char *s, size_t n, char *p)
1721 {
1722         p = makestrspace(n, p);
1723         p = (char *)mempcpy(p, s, n);
1724         return p;
1725 }
1726
1727 static char *
1728 stack_putstr(const char *s, char *p)
1729 {
1730         return stack_nputstr(s, strlen(s), p);
1731 }
1732
1733 static char *
1734 _STPUTC(int c, char *p)
1735 {
1736         if (p == sstrend)
1737                 p = growstackstr();
1738         *p++ = c;
1739         return p;
1740 }
1741
1742 #define STARTSTACKSTR(p)        ((p) = stackblock())
1743 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1744 #define CHECKSTRSPACE(n, p) do { \
1745         char *q = (p); \
1746         size_t l = (n); \
1747         size_t m = sstrend - q; \
1748         if (l > m) \
1749                 (p) = makestrspace(l, q); \
1750 } while (0)
1751 #define USTPUTC(c, p)           (*(p)++ = (c))
1752 #define STACKSTRNUL(p) do { \
1753         if ((p) == sstrend) \
1754                 (p) = growstackstr(); \
1755         *(p) = '\0'; \
1756 } while (0)
1757 #define STUNPUTC(p)             (--(p))
1758 #define STTOPC(p)               ((p)[-1])
1759 #define STADJUST(amount, p)     ((p) += (amount))
1760
1761 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1762 #define ungrabstackstr(s, p)    stunalloc(s)
1763 #define stackstrend()           ((void *)sstrend)
1764
1765
1766 /* ============ String helpers */
1767
1768 /*
1769  * prefix -- see if pfx is a prefix of string.
1770  */
1771 static char *
1772 prefix(const char *string, const char *pfx)
1773 {
1774         while (*pfx) {
1775                 if (*pfx++ != *string++)
1776                         return NULL;
1777         }
1778         return (char *) string;
1779 }
1780
1781 /*
1782  * Check for a valid number.  This should be elsewhere.
1783  */
1784 static int
1785 is_number(const char *p)
1786 {
1787         do {
1788                 if (!isdigit(*p))
1789                         return 0;
1790         } while (*++p != '\0');
1791         return 1;
1792 }
1793
1794 /*
1795  * Convert a string of digits to an integer, printing an error message on
1796  * failure.
1797  */
1798 static int
1799 number(const char *s)
1800 {
1801         if (!is_number(s))
1802                 ash_msg_and_raise_error(msg_illnum, s);
1803         return atoi(s);
1804 }
1805
1806 /*
1807  * Produce a single quoted string suitable as input to the shell.
1808  * The return string is allocated on the stack.
1809  */
1810 static char *
1811 single_quote(const char *s)
1812 {
1813         char *p;
1814
1815         STARTSTACKSTR(p);
1816
1817         do {
1818                 char *q;
1819                 size_t len;
1820
1821                 len = strchrnul(s, '\'') - s;
1822
1823                 q = p = makestrspace(len + 3, p);
1824
1825                 *q++ = '\'';
1826                 q = (char *)mempcpy(q, s, len);
1827                 *q++ = '\'';
1828                 s += len;
1829
1830                 STADJUST(q - p, p);
1831
1832                 if (*s != '\'')
1833                         break;
1834                 len = 0;
1835                 do len++; while (*++s == '\'');
1836
1837                 q = p = makestrspace(len + 3, p);
1838
1839                 *q++ = '"';
1840                 q = (char *)mempcpy(q, s - len, len);
1841                 *q++ = '"';
1842
1843                 STADJUST(q - p, p);
1844         } while (*s);
1845
1846         USTPUTC('\0', p);
1847
1848         return stackblock();
1849 }
1850
1851 /*
1852  * Produce a possibly single quoted string suitable as input to the shell.
1853  * If quoting was done, the return string is allocated on the stack,
1854  * otherwise a pointer to the original string is returned.
1855  */
1856 static const char *
1857 maybe_single_quote(const char *s)
1858 {
1859         const char *p = s;
1860
1861         while (*p) {
1862                 /* Assuming ACSII */
1863                 /* quote ctrl_chars space !"#$%&'()* */
1864                 if (*p < '+')
1865                         goto need_quoting;
1866                 /* quote ;<=>? */
1867                 if (*p >= ';' && *p <= '?')
1868                         goto need_quoting;
1869                 /* quote `[\ */
1870                 if (*p == '`')
1871                         goto need_quoting;
1872                 if (*p == '[')
1873                         goto need_quoting;
1874                 if (*p == '\\')
1875                         goto need_quoting;
1876                 /* quote {|}~ DEL and high bytes */
1877                 if (*p > 'z')
1878                         goto need_quoting;
1879                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1880                 /* TODO: maybe avoid quoting % */
1881                 p++;
1882         }
1883         return s;
1884
1885  need_quoting:
1886         return single_quote(s);
1887 }
1888
1889
1890 /* ============ nextopt */
1891
1892 static char **argptr;                  /* argument list for builtin commands */
1893 static char *optionarg;                /* set by nextopt (like getopt) */
1894 static char *optptr;                   /* used by nextopt */
1895
1896 /*
1897  * XXX - should get rid of. Have all builtins use getopt(3).
1898  * The library getopt must have the BSD extension static variable
1899  * "optreset", otherwise it can't be used within the shell safely.
1900  *
1901  * Standard option processing (a la getopt) for builtin routines.
1902  * The only argument that is passed to nextopt is the option string;
1903  * the other arguments are unnecessary. It returns the character,
1904  * or '\0' on end of input.
1905  */
1906 static int
1907 nextopt(const char *optstring)
1908 {
1909         char *p;
1910         const char *q;
1911         char c;
1912
1913         p = optptr;
1914         if (p == NULL || *p == '\0') {
1915                 /* We ate entire "-param", take next one */
1916                 p = *argptr;
1917                 if (p == NULL)
1918                         return '\0';
1919                 if (*p != '-')
1920                         return '\0';
1921                 if (*++p == '\0') /* just "-" ? */
1922                         return '\0';
1923                 argptr++;
1924                 if (LONE_DASH(p)) /* "--" ? */
1925                         return '\0';
1926                 /* p => next "-param" */
1927         }
1928         /* p => some option char in the middle of a "-param" */
1929         c = *p++;
1930         for (q = optstring; *q != c;) {
1931                 if (*q == '\0')
1932                         ash_msg_and_raise_error("illegal option -%c", c);
1933                 if (*++q == ':')
1934                         q++;
1935         }
1936         if (*++q == ':') {
1937                 if (*p == '\0') {
1938                         p = *argptr++;
1939                         if (p == NULL)
1940                                 ash_msg_and_raise_error("no arg for -%c option", c);
1941                 }
1942                 optionarg = p;
1943                 p = NULL;
1944         }
1945         optptr = p;
1946         return c;
1947 }
1948
1949
1950 /* ============ Shell variables */
1951
1952 struct shparam {
1953         int nparam;             /* # of positional parameters (without $0) */
1954 #if ENABLE_ASH_GETOPTS
1955         int optind;             /* next parameter to be processed by getopts */
1956         int optoff;             /* used by getopts */
1957 #endif
1958         unsigned char malloced; /* if parameter list dynamically allocated */
1959         char **p;               /* parameter list */
1960 };
1961
1962 /*
1963  * Free the list of positional parameters.
1964  */
1965 static void
1966 freeparam(volatile struct shparam *param)
1967 {
1968         if (param->malloced) {
1969                 char **ap, **ap1;
1970                 ap = ap1 = param->p;
1971                 while (*ap)
1972                         free(*ap++);
1973                 free(ap1);
1974         }
1975 }
1976
1977 #if ENABLE_ASH_GETOPTS
1978 static void FAST_FUNC getoptsreset(const char *value);
1979 #endif
1980
1981 struct var {
1982         struct var *next;               /* next entry in hash list */
1983         int flags;                      /* flags are defined above */
1984         const char *var_text;           /* name=value */
1985         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1986                                         /* the variable gets set/unset */
1987 };
1988
1989 struct localvar {
1990         struct localvar *next;          /* next local variable in list */
1991         struct var *vp;                 /* the variable that was made local */
1992         int flags;                      /* saved flags */
1993         const char *text;               /* saved text */
1994 };
1995
1996 /* flags */
1997 #define VEXPORT         0x01    /* variable is exported */
1998 #define VREADONLY       0x02    /* variable cannot be modified */
1999 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2000 #define VTEXTFIXED      0x08    /* text is statically allocated */
2001 #define VSTACK          0x10    /* text is allocated on the stack */
2002 #define VUNSET          0x20    /* the variable is not set */
2003 #define VNOFUNC         0x40    /* don't call the callback function */
2004 #define VNOSET          0x80    /* do not set variable - just readonly test */
2005 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2006 #if ENABLE_ASH_RANDOM_SUPPORT
2007 # define VDYNAMIC       0x200   /* dynamic variable */
2008 #else
2009 # define VDYNAMIC       0
2010 #endif
2011
2012
2013 /* Need to be before varinit_data[] */
2014 #if ENABLE_LOCALE_SUPPORT
2015 static void FAST_FUNC
2016 change_lc_all(const char *value)
2017 {
2018         if (value && *value != '\0')
2019                 setlocale(LC_ALL, value);
2020 }
2021 static void FAST_FUNC
2022 change_lc_ctype(const char *value)
2023 {
2024         if (value && *value != '\0')
2025                 setlocale(LC_CTYPE, value);
2026 }
2027 #endif
2028 #if ENABLE_ASH_MAIL
2029 static void chkmail(void);
2030 static void changemail(const char *var_value) FAST_FUNC;
2031 #else
2032 # define chkmail()  ((void)0)
2033 #endif
2034 static void changepath(const char *) FAST_FUNC;
2035 #if ENABLE_ASH_RANDOM_SUPPORT
2036 static void change_random(const char *) FAST_FUNC;
2037 #endif
2038
2039 static const struct {
2040         int flags;
2041         const char *var_text;
2042         void (*var_func)(const char *) FAST_FUNC;
2043 } varinit_data[] = {
2044         /*
2045          * Note: VEXPORT would not work correctly here for NOFORK applets:
2046          * some environment strings may be constant.
2047          */
2048         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2049 #if ENABLE_ASH_MAIL
2050         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2051         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2052 #endif
2053         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2054         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2055         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2056         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2057 #if ENABLE_ASH_GETOPTS
2058         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2059 #endif
2060         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2061 #if ENABLE_ASH_RANDOM_SUPPORT
2062         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2063 #endif
2064 #if ENABLE_LOCALE_SUPPORT
2065         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2066         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2067 #endif
2068 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2069         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2070 #endif
2071 };
2072
2073 struct redirtab;
2074
2075 struct globals_var {
2076         struct shparam shellparam;      /* $@ current positional parameters */
2077         struct redirtab *redirlist;
2078         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2079         struct var *vartab[VTABSIZE];
2080         struct var varinit[ARRAY_SIZE(varinit_data)];
2081         int lineno;
2082         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2083 };
2084 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2085 #define G_var (*ash_ptr_to_globals_var)
2086 #define shellparam    (G_var.shellparam   )
2087 //#define redirlist     (G_var.redirlist    )
2088 #define preverrout_fd (G_var.preverrout_fd)
2089 #define vartab        (G_var.vartab       )
2090 #define varinit       (G_var.varinit      )
2091 #define lineno        (G_var.lineno       )
2092 #define linenovar     (G_var.linenovar    )
2093 #define vifs      varinit[0]
2094 #if ENABLE_ASH_MAIL
2095 # define vmail    (&vifs)[1]
2096 # define vmpath   (&vmail)[1]
2097 # define vpath    (&vmpath)[1]
2098 #else
2099 # define vpath    (&vifs)[1]
2100 #endif
2101 #define vps1      (&vpath)[1]
2102 #define vps2      (&vps1)[1]
2103 #define vps4      (&vps2)[1]
2104 #if ENABLE_ASH_GETOPTS
2105 # define voptind  (&vps4)[1]
2106 # define vlineno  (&voptind)[1]
2107 # if ENABLE_ASH_RANDOM_SUPPORT
2108 #  define vrandom (&vlineno)[1]
2109 # endif
2110 #else
2111 # define vlineno  (&vps4)[1]
2112 # if ENABLE_ASH_RANDOM_SUPPORT
2113 #  define vrandom (&vlineno)[1]
2114 # endif
2115 #endif
2116 #define INIT_G_var() do { \
2117         unsigned i; \
2118         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2119         barrier(); \
2120         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2121                 varinit[i].flags    = varinit_data[i].flags; \
2122                 varinit[i].var_text = varinit_data[i].var_text; \
2123                 varinit[i].var_func = varinit_data[i].var_func; \
2124         } \
2125         strcpy(linenovar, "LINENO="); \
2126         vlineno.var_text = linenovar; \
2127 } while (0)
2128
2129 /*
2130  * The following macros access the values of the above variables.
2131  * They have to skip over the name.  They return the null string
2132  * for unset variables.
2133  */
2134 #define ifsval()        (vifs.var_text + 4)
2135 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2136 #if ENABLE_ASH_MAIL
2137 # define mailval()      (vmail.var_text + 5)
2138 # define mpathval()     (vmpath.var_text + 9)
2139 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2140 #endif
2141 #define pathval()       (vpath.var_text + 5)
2142 #define ps1val()        (vps1.var_text + 4)
2143 #define ps2val()        (vps2.var_text + 4)
2144 #define ps4val()        (vps4.var_text + 4)
2145 #if ENABLE_ASH_GETOPTS
2146 # define optindval()    (voptind.var_text + 7)
2147 #endif
2148
2149 #if ENABLE_ASH_GETOPTS
2150 static void FAST_FUNC
2151 getoptsreset(const char *value)
2152 {
2153         shellparam.optind = 1;
2154         if (is_number(value))
2155                 shellparam.optind = number(value) ?: 1;
2156         shellparam.optoff = -1;
2157 }
2158 #endif
2159
2160 /*
2161  * Compares two strings up to the first = or '\0'.  The first
2162  * string must be terminated by '='; the second may be terminated by
2163  * either '=' or '\0'.
2164  */
2165 static int
2166 varcmp(const char *p, const char *q)
2167 {
2168         int c, d;
2169
2170         while ((c = *p) == (d = *q)) {
2171                 if (c == '\0' || c == '=')
2172                         goto out;
2173                 p++;
2174                 q++;
2175         }
2176         if (c == '=')
2177                 c = '\0';
2178         if (d == '=')
2179                 d = '\0';
2180  out:
2181         return c - d;
2182 }
2183
2184 /*
2185  * Find the appropriate entry in the hash table from the name.
2186  */
2187 static struct var **
2188 hashvar(const char *p)
2189 {
2190         unsigned hashval;
2191
2192         hashval = ((unsigned char) *p) << 4;
2193         while (*p && *p != '=')
2194                 hashval += (unsigned char) *p++;
2195         return &vartab[hashval % VTABSIZE];
2196 }
2197
2198 static int
2199 vpcmp(const void *a, const void *b)
2200 {
2201         return varcmp(*(const char **)a, *(const char **)b);
2202 }
2203
2204 /*
2205  * This routine initializes the builtin variables.
2206  */
2207 static void
2208 initvar(void)
2209 {
2210         struct var *vp;
2211         struct var *end;
2212         struct var **vpp;
2213
2214         /*
2215          * PS1 depends on uid
2216          */
2217 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2218         vps1.var_text = "PS1=\\w \\$ ";
2219 #else
2220         if (!geteuid())
2221                 vps1.var_text = "PS1=# ";
2222 #endif
2223         vp = varinit;
2224         end = vp + ARRAY_SIZE(varinit);
2225         do {
2226                 vpp = hashvar(vp->var_text);
2227                 vp->next = *vpp;
2228                 *vpp = vp;
2229         } while (++vp < end);
2230 }
2231
2232 static struct var **
2233 findvar(struct var **vpp, const char *name)
2234 {
2235         for (; *vpp; vpp = &(*vpp)->next) {
2236                 if (varcmp((*vpp)->var_text, name) == 0) {
2237                         break;
2238                 }
2239         }
2240         return vpp;
2241 }
2242
2243 /*
2244  * Find the value of a variable.  Returns NULL if not set.
2245  */
2246 static const char* FAST_FUNC
2247 lookupvar(const char *name)
2248 {
2249         struct var *v;
2250
2251         v = *findvar(hashvar(name), name);
2252         if (v) {
2253 #if ENABLE_ASH_RANDOM_SUPPORT
2254         /*
2255          * Dynamic variables are implemented roughly the same way they are
2256          * in bash. Namely, they're "special" so long as they aren't unset.
2257          * As soon as they're unset, they're no longer dynamic, and dynamic
2258          * lookup will no longer happen at that point. -- PFM.
2259          */
2260                 if (v->flags & VDYNAMIC)
2261                         v->var_func(NULL);
2262 #endif
2263                 if (!(v->flags & VUNSET)) {
2264                         if (v == &vlineno && v->var_text == linenovar) {
2265                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2266                         }
2267                         return var_end(v->var_text);
2268                 }
2269         }
2270         return NULL;
2271 }
2272
2273 #if ENABLE_UNICODE_SUPPORT
2274 static void
2275 reinit_unicode_for_ash(void)
2276 {
2277         /* Unicode support should be activated even if LANG is set
2278          * _during_ shell execution, not only if it was set when
2279          * shell was started. Therefore, re-check LANG every time:
2280          */
2281         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2282          || ENABLE_UNICODE_USING_LOCALE
2283         ) {
2284                 const char *s = lookupvar("LC_ALL");
2285                 if (!s) s = lookupvar("LC_CTYPE");
2286                 if (!s) s = lookupvar("LANG");
2287                 reinit_unicode(s);
2288         }
2289 }
2290 #else
2291 # define reinit_unicode_for_ash() ((void)0)
2292 #endif
2293
2294 /*
2295  * Search the environment of a builtin command.
2296  */
2297 static ALWAYS_INLINE const char *
2298 bltinlookup(const char *name)
2299 {
2300         return lookupvar(name);
2301 }
2302
2303 /*
2304  * Same as setvar except that the variable and value are passed in
2305  * the first argument as name=value.  Since the first argument will
2306  * be actually stored in the table, it should not be a string that
2307  * will go away.
2308  * Called with interrupts off.
2309  */
2310 static struct var *
2311 setvareq(char *s, int flags)
2312 {
2313         struct var *vp, **vpp;
2314
2315         vpp = hashvar(s);
2316         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2317         vpp = findvar(vpp, s);
2318         vp = *vpp;
2319         if (vp) {
2320                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2321                         const char *n;
2322
2323                         if (flags & VNOSAVE)
2324                                 free(s);
2325                         n = vp->var_text;
2326                         exitstatus = 1;
2327                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2328                 }
2329
2330                 if (flags & VNOSET)
2331                         goto out;
2332
2333                 if (vp->var_func && !(flags & VNOFUNC))
2334                         vp->var_func(var_end(s));
2335
2336                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2337                         free((char*)vp->var_text);
2338
2339                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2340                         *vpp = vp->next;
2341                         free(vp);
2342  out_free:
2343                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2344                                 free(s);
2345                         goto out;
2346                 }
2347
2348                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2349         } else {
2350                 /* variable s is not found */
2351                 if (flags & VNOSET)
2352                         goto out;
2353                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2354                         goto out_free;
2355                 vp = ckzalloc(sizeof(*vp));
2356                 vp->next = *vpp;
2357                 /*vp->func = NULL; - ckzalloc did it */
2358                 *vpp = vp;
2359         }
2360         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2361                 s = ckstrdup(s);
2362         vp->var_text = s;
2363         vp->flags = flags;
2364
2365  out:
2366         return vp;
2367 }
2368
2369 /*
2370  * Set the value of a variable.  The flags argument is ored with the
2371  * flags of the variable.  If val is NULL, the variable is unset.
2372  */
2373 static struct var *
2374 setvar(const char *name, const char *val, int flags)
2375 {
2376         const char *q;
2377         char *p;
2378         char *nameeq;
2379         size_t namelen;
2380         size_t vallen;
2381         struct var *vp;
2382
2383         q = endofname(name);
2384         p = strchrnul(q, '=');
2385         namelen = p - name;
2386         if (!namelen || p != q)
2387                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2388         vallen = 0;
2389         if (val == NULL) {
2390                 flags |= VUNSET;
2391         } else {
2392                 vallen = strlen(val);
2393         }
2394
2395         INT_OFF;
2396         nameeq = ckmalloc(namelen + vallen + 2);
2397         p = mempcpy(nameeq, name, namelen);
2398         if (val) {
2399                 *p++ = '=';
2400                 p = mempcpy(p, val, vallen);
2401         }
2402         *p = '\0';
2403         vp = setvareq(nameeq, flags | VNOSAVE);
2404         INT_ON;
2405
2406         return vp;
2407 }
2408
2409 static void FAST_FUNC
2410 setvar0(const char *name, const char *val)
2411 {
2412         setvar(name, val, 0);
2413 }
2414
2415 /*
2416  * Unset the specified variable.
2417  */
2418 static void
2419 unsetvar(const char *s)
2420 {
2421         setvar(s, NULL, 0);
2422 }
2423
2424 /*
2425  * Process a linked list of variable assignments.
2426  */
2427 static void
2428 listsetvar(struct strlist *list_set_var, int flags)
2429 {
2430         struct strlist *lp = list_set_var;
2431
2432         if (!lp)
2433                 return;
2434         INT_OFF;
2435         do {
2436                 setvareq(lp->text, flags);
2437                 lp = lp->next;
2438         } while (lp);
2439         INT_ON;
2440 }
2441
2442 /*
2443  * Generate a list of variables satisfying the given conditions.
2444  */
2445 #if !ENABLE_FEATURE_SH_NOFORK
2446 # define listvars(on, off, lp, end) listvars(on, off, end)
2447 #endif
2448 static char **
2449 listvars(int on, int off, struct strlist *lp, char ***end)
2450 {
2451         struct var **vpp;
2452         struct var *vp;
2453         char **ep;
2454         int mask;
2455
2456         STARTSTACKSTR(ep);
2457         vpp = vartab;
2458         mask = on | off;
2459         do {
2460                 for (vp = *vpp; vp; vp = vp->next) {
2461                         if ((vp->flags & mask) == on) {
2462 #if ENABLE_FEATURE_SH_NOFORK
2463                                 /* If variable with the same name is both
2464                                  * exported and temporarily set for a command:
2465                                  *  export ZVAR=5
2466                                  *  ZVAR=6 printenv
2467                                  * then "ZVAR=6" will be both in vartab and
2468                                  * lp lists. Do not pass it twice to printenv.
2469                                  */
2470                                 struct strlist *lp1 = lp;
2471                                 while (lp1) {
2472                                         if (strcmp(lp1->text, vp->var_text) == 0)
2473                                                 goto skip;
2474                                         lp1 = lp1->next;
2475                                 }
2476 #endif
2477                                 if (ep == stackstrend())
2478                                         ep = growstackstr();
2479                                 *ep++ = (char*)vp->var_text;
2480 #if ENABLE_FEATURE_SH_NOFORK
2481  skip: ;
2482 #endif
2483                         }
2484                 }
2485         } while (++vpp < vartab + VTABSIZE);
2486
2487 #if ENABLE_FEATURE_SH_NOFORK
2488         while (lp) {
2489                 if (ep == stackstrend())
2490                         ep = growstackstr();
2491                 *ep++ = lp->text;
2492                 lp = lp->next;
2493         }
2494 #endif
2495
2496         if (ep == stackstrend())
2497                 ep = growstackstr();
2498         if (end)
2499                 *end = ep;
2500         *ep++ = NULL;
2501         return grabstackstr(ep);
2502 }
2503
2504
2505 /* ============ Path search helper
2506  *
2507  * The variable path (passed by reference) should be set to the start
2508  * of the path before the first call; path_advance will update
2509  * this value as it proceeds.  Successive calls to path_advance will return
2510  * the possible path expansions in sequence.  If an option (indicated by
2511  * a percent sign) appears in the path entry then the global variable
2512  * pathopt will be set to point to it; otherwise pathopt will be set to
2513  * NULL.
2514  */
2515 static const char *pathopt;     /* set by path_advance */
2516
2517 static char *
2518 path_advance(const char **path, const char *name)
2519 {
2520         const char *p;
2521         char *q;
2522         const char *start;
2523         size_t len;
2524
2525         if (*path == NULL)
2526                 return NULL;
2527         start = *path;
2528         for (p = start; *p && *p != ':' && *p != '%'; p++)
2529                 continue;
2530         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2531         while (stackblocksize() < len)
2532                 growstackblock();
2533         q = stackblock();
2534         if (p != start) {
2535                 q = mempcpy(q, start, p - start);
2536                 *q++ = '/';
2537         }
2538         strcpy(q, name);
2539         pathopt = NULL;
2540         if (*p == '%') {
2541                 pathopt = ++p;
2542                 while (*p && *p != ':')
2543                         p++;
2544         }
2545         if (*p == ':')
2546                 *path = p + 1;
2547         else
2548                 *path = NULL;
2549         return stalloc(len);
2550 }
2551
2552
2553 /* ============ Prompt */
2554
2555 static smallint doprompt;                   /* if set, prompt the user */
2556 static smallint needprompt;                 /* true if interactive and at start of line */
2557
2558 #if ENABLE_FEATURE_EDITING
2559 static line_input_t *line_input_state;
2560 static const char *cmdedit_prompt;
2561 static void
2562 putprompt(const char *s)
2563 {
2564         if (ENABLE_ASH_EXPAND_PRMT) {
2565                 free((char*)cmdedit_prompt);
2566                 cmdedit_prompt = ckstrdup(s);
2567                 return;
2568         }
2569         cmdedit_prompt = s;
2570 }
2571 #else
2572 static void
2573 putprompt(const char *s)
2574 {
2575         out2str(s);
2576 }
2577 #endif
2578
2579 /* expandstr() needs parsing machinery, so it is far away ahead... */
2580 static const char *expandstr(const char *ps, int syntax_type);
2581 /* Values for syntax param */
2582 #define BASESYNTAX 0    /* not in quotes */
2583 #define DQSYNTAX   1    /* in double quotes */
2584 #define SQSYNTAX   2    /* in single quotes */
2585 #define ARISYNTAX  3    /* in arithmetic */
2586 #if ENABLE_ASH_EXPAND_PRMT
2587 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2588 #endif
2589 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2590
2591 /*
2592  * called by editline -- any expansions to the prompt should be added here.
2593  */
2594 static void
2595 setprompt_if(smallint do_set, int whichprompt)
2596 {
2597         const char *prompt;
2598         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2599
2600         if (!do_set)
2601                 return;
2602
2603         needprompt = 0;
2604
2605         switch (whichprompt) {
2606         case 1:
2607                 prompt = ps1val();
2608                 break;
2609         case 2:
2610                 prompt = ps2val();
2611                 break;
2612         default:                        /* 0 */
2613                 prompt = nullstr;
2614         }
2615 #if ENABLE_ASH_EXPAND_PRMT
2616         pushstackmark(&smark, stackblocksize());
2617         putprompt(expandstr(prompt, PSSYNTAX));
2618         popstackmark(&smark);
2619 #else
2620         putprompt(prompt);
2621 #endif
2622 }
2623
2624
2625 /* ============ The cd and pwd commands */
2626
2627 #define CD_PHYSICAL 1
2628 #define CD_PRINT 2
2629
2630 static int
2631 cdopt(void)
2632 {
2633         int flags = 0;
2634         int i, j;
2635
2636         j = 'L';
2637         while ((i = nextopt("LP")) != '\0') {
2638                 if (i != j) {
2639                         flags ^= CD_PHYSICAL;
2640                         j = i;
2641                 }
2642         }
2643
2644         return flags;
2645 }
2646
2647 /*
2648  * Update curdir (the name of the current directory) in response to a
2649  * cd command.
2650  */
2651 static const char *
2652 updatepwd(const char *dir)
2653 {
2654         char *new;
2655         char *p;
2656         char *cdcomppath;
2657         const char *lim;
2658
2659         cdcomppath = sstrdup(dir);
2660         STARTSTACKSTR(new);
2661         if (*dir != '/') {
2662                 if (curdir == nullstr)
2663                         return 0;
2664                 new = stack_putstr(curdir, new);
2665         }
2666         new = makestrspace(strlen(dir) + 2, new);
2667         lim = (char *)stackblock() + 1;
2668         if (*dir != '/') {
2669                 if (new[-1] != '/')
2670                         USTPUTC('/', new);
2671                 if (new > lim && *lim == '/')
2672                         lim++;
2673         } else {
2674                 USTPUTC('/', new);
2675                 cdcomppath++;
2676                 if (dir[1] == '/' && dir[2] != '/') {
2677                         USTPUTC('/', new);
2678                         cdcomppath++;
2679                         lim++;
2680                 }
2681         }
2682         p = strtok(cdcomppath, "/");
2683         while (p) {
2684                 switch (*p) {
2685                 case '.':
2686                         if (p[1] == '.' && p[2] == '\0') {
2687                                 while (new > lim) {
2688                                         STUNPUTC(new);
2689                                         if (new[-1] == '/')
2690                                                 break;
2691                                 }
2692                                 break;
2693                         }
2694                         if (p[1] == '\0')
2695                                 break;
2696                         /* fall through */
2697                 default:
2698                         new = stack_putstr(p, new);
2699                         USTPUTC('/', new);
2700                 }
2701                 p = strtok(NULL, "/");
2702         }
2703         if (new > lim)
2704                 STUNPUTC(new);
2705         *new = 0;
2706         return stackblock();
2707 }
2708
2709 /*
2710  * Find out what the current directory is. If we already know the current
2711  * directory, this routine returns immediately.
2712  */
2713 static char *
2714 getpwd(void)
2715 {
2716         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2717         return dir ? dir : nullstr;
2718 }
2719
2720 static void
2721 setpwd(const char *val, int setold)
2722 {
2723         char *oldcur, *dir;
2724
2725         oldcur = dir = curdir;
2726
2727         if (setold) {
2728                 setvar("OLDPWD", oldcur, VEXPORT);
2729         }
2730         INT_OFF;
2731         if (physdir != nullstr) {
2732                 if (physdir != oldcur)
2733                         free(physdir);
2734                 physdir = nullstr;
2735         }
2736         if (oldcur == val || !val) {
2737                 char *s = getpwd();
2738                 physdir = s;
2739                 if (!val)
2740                         dir = s;
2741         } else
2742                 dir = ckstrdup(val);
2743         if (oldcur != dir && oldcur != nullstr) {
2744                 free(oldcur);
2745         }
2746         curdir = dir;
2747         INT_ON;
2748         setvar("PWD", dir, VEXPORT);
2749 }
2750
2751 static void hashcd(void);
2752
2753 /*
2754  * Actually do the chdir.  We also call hashcd to let other routines
2755  * know that the current directory has changed.
2756  */
2757 static int
2758 docd(const char *dest, int flags)
2759 {
2760         const char *dir = NULL;
2761         int err;
2762
2763         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2764
2765         INT_OFF;
2766         if (!(flags & CD_PHYSICAL)) {
2767                 dir = updatepwd(dest);
2768                 if (dir)
2769                         dest = dir;
2770         }
2771         err = chdir(dest);
2772         if (err)
2773                 goto out;
2774         setpwd(dir, 1);
2775         hashcd();
2776  out:
2777         INT_ON;
2778         return err;
2779 }
2780
2781 static int FAST_FUNC
2782 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2783 {
2784         const char *dest;
2785         const char *path;
2786         const char *p;
2787         char c;
2788         struct stat statb;
2789         int flags;
2790
2791         flags = cdopt();
2792         dest = *argptr;
2793         if (!dest)
2794                 dest = bltinlookup("HOME");
2795         else if (LONE_DASH(dest)) {
2796                 dest = bltinlookup("OLDPWD");
2797                 flags |= CD_PRINT;
2798         }
2799         if (!dest)
2800                 dest = nullstr;
2801         if (*dest == '/')
2802                 goto step6;
2803         if (*dest == '.') {
2804                 c = dest[1];
2805  dotdot:
2806                 switch (c) {
2807                 case '\0':
2808                 case '/':
2809                         goto step6;
2810                 case '.':
2811                         c = dest[2];
2812                         if (c != '.')
2813                                 goto dotdot;
2814                 }
2815         }
2816         if (!*dest)
2817                 dest = ".";
2818         path = bltinlookup("CDPATH");
2819         while (path) {
2820                 c = *path;
2821                 p = path_advance(&path, dest);
2822                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2823                         if (c && c != ':')
2824                                 flags |= CD_PRINT;
2825  docd:
2826                         if (!docd(p, flags))
2827                                 goto out;
2828                         goto err;
2829                 }
2830         }
2831
2832  step6:
2833         p = dest;
2834         goto docd;
2835
2836  err:
2837         ash_msg_and_raise_perror("can't cd to %s", dest);
2838         /* NOTREACHED */
2839  out:
2840         if (flags & CD_PRINT)
2841                 out1fmt("%s\n", curdir);
2842         return 0;
2843 }
2844
2845 static int FAST_FUNC
2846 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2847 {
2848         int flags;
2849         const char *dir = curdir;
2850
2851         flags = cdopt();
2852         if (flags) {
2853                 if (physdir == nullstr)
2854                         setpwd(dir, 0);
2855                 dir = physdir;
2856         }
2857         out1fmt("%s\n", dir);
2858         return 0;
2859 }
2860
2861
2862 /* ============ ... */
2863
2864
2865 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2866
2867 /* Syntax classes */
2868 #define CWORD     0             /* character is nothing special */
2869 #define CNL       1             /* newline character */
2870 #define CBACK     2             /* a backslash character */
2871 #define CSQUOTE   3             /* single quote */
2872 #define CDQUOTE   4             /* double quote */
2873 #define CENDQUOTE 5             /* a terminating quote */
2874 #define CBQUOTE   6             /* backwards single quote */
2875 #define CVAR      7             /* a dollar sign */
2876 #define CENDVAR   8             /* a '}' character */
2877 #define CLP       9             /* a left paren in arithmetic */
2878 #define CRP      10             /* a right paren in arithmetic */
2879 #define CENDFILE 11             /* end of file */
2880 #define CCTL     12             /* like CWORD, except it must be escaped */
2881 #define CSPCL    13             /* these terminate a word */
2882 #define CIGN     14             /* character should be ignored */
2883
2884 #define PEOF     256
2885 #if ENABLE_ASH_ALIAS
2886 # define PEOA    257
2887 #endif
2888
2889 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2890
2891 #if ENABLE_FEATURE_SH_MATH
2892 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2893 #else
2894 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2895 #endif
2896 static const uint16_t S_I_T[] ALIGN2 = {
2897 #if ENABLE_ASH_ALIAS
2898         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2899 #endif
2900         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2901         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2902         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2903         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2904         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2905         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2906         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2907         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2908         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2909         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2910         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2911 #if !USE_SIT_FUNCTION
2912         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2913         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2914         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2915 #endif
2916 #undef SIT_ITEM
2917 };
2918 /* Constants below must match table above */
2919 enum {
2920 #if ENABLE_ASH_ALIAS
2921         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2922 #endif
2923         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2924         CNL_CNL_CNL_CNL                    , /*  2 */
2925         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2926         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2927         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2928         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2929         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2930         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2931         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2932         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2933         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2934         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2935         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2936         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2937 };
2938
2939 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2940  * caller must ensure proper cast on it if c is *char_ptr!
2941  */
2942 #if USE_SIT_FUNCTION
2943
2944 static int
2945 SIT(int c, int syntax)
2946 {
2947         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2948         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2949         /*
2950          * This causes '/' to be prepended with CTLESC in dquoted string,
2951          * making "./file"* treated incorrectly because we feed
2952          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2953          * The "homegrown" glob implementation is okay with that,
2954          * but glibc one isn't. With '/' always treated as CWORD,
2955          * both work fine.
2956          */
2957 # if ENABLE_ASH_ALIAS
2958         static const uint8_t syntax_index_table[] ALIGN1 = {
2959                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2960                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2961                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2962                 11, 3                           /* "}~" */
2963         };
2964 # else
2965         static const uint8_t syntax_index_table[] ALIGN1 = {
2966                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2967                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2968                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2969                 10, 2                           /* "}~" */
2970         };
2971 # endif
2972         const char *s;
2973         int indx;
2974
2975         if (c == PEOF)
2976                 return CENDFILE;
2977 # if ENABLE_ASH_ALIAS
2978         if (c == PEOA)
2979                 indx = 0;
2980         else
2981 # endif
2982         {
2983                 /* Cast is purely for paranoia here,
2984                  * just in case someone passed signed char to us */
2985                 if ((unsigned char)c >= CTL_FIRST
2986                  && (unsigned char)c <= CTL_LAST
2987                 ) {
2988                         return CCTL;
2989                 }
2990                 s = strchrnul(spec_symbls, c);
2991                 if (*s == '\0')
2992                         return CWORD;
2993                 indx = syntax_index_table[s - spec_symbls];
2994         }
2995         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2996 }
2997
2998 #else   /* !USE_SIT_FUNCTION */
2999
3000 static const uint8_t syntax_index_table[] ALIGN1 = {
3001         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3002         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3003         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3004         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3005         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3006         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3007         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3008         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3009         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3010         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3011         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3012         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3013         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3014         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3015         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3016         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3017         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3018         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3019         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3020         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3021         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3022         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3023         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3024         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3025         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3029         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3030         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3031         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3032         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3033         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3034         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3035         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3036         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3037         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3038         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3039         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3040         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3041         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3042         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3043         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3044         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3045         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3046         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3047         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3048         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3049 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3050         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3051         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3053         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3054         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3055         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3056         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3057         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3059         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3060         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3061         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3062         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3063         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3064         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3065         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3066         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3067         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3074         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3075         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3076         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3077         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3078         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3089         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3090         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3092         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3094         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3095         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3096         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3097         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3100         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3102         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3103         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3104         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3105         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3106         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3107         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3108         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3109         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3110         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3111         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3112         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3113         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3114         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3122         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3123         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3124         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3125         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3126         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3127         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3128         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3129         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3130         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3131         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3132         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3133         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3134         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3135         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3136         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3137         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3138         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3139         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3140         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3259         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3260 # if ENABLE_ASH_ALIAS
3261         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3262 # endif
3263 };
3264
3265 #if 1
3266 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3267 #else /* debug version, caught one signed char bug */
3268 # define SIT(c, syntax) \
3269         ({ \
3270                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3271                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3272                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3273                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3274                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3275         })
3276 #endif
3277
3278 #endif  /* !USE_SIT_FUNCTION */
3279
3280
3281 /* ============ Alias handling */
3282
3283 #if ENABLE_ASH_ALIAS
3284
3285 #define ALIASINUSE 1
3286 #define ALIASDEAD  2
3287
3288 struct alias {
3289         struct alias *next;
3290         char *name;
3291         char *val;
3292         int flag;
3293 };
3294
3295
3296 static struct alias **atab; // [ATABSIZE];
3297 #define INIT_G_alias() do { \
3298         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3299 } while (0)
3300
3301
3302 static struct alias **
3303 __lookupalias(const char *name)
3304 {
3305         unsigned int hashval;
3306         struct alias **app;
3307         const char *p;
3308         unsigned int ch;
3309
3310         p = name;
3311
3312         ch = (unsigned char)*p;
3313         hashval = ch << 4;
3314         while (ch) {
3315                 hashval += ch;
3316                 ch = (unsigned char)*++p;
3317         }
3318         app = &atab[hashval % ATABSIZE];
3319
3320         for (; *app; app = &(*app)->next) {
3321                 if (strcmp(name, (*app)->name) == 0) {
3322                         break;
3323                 }
3324         }
3325
3326         return app;
3327 }
3328
3329 static struct alias *
3330 lookupalias(const char *name, int check)
3331 {
3332         struct alias *ap = *__lookupalias(name);
3333
3334         if (check && ap && (ap->flag & ALIASINUSE))
3335                 return NULL;
3336         return ap;
3337 }
3338
3339 static struct alias *
3340 freealias(struct alias *ap)
3341 {
3342         struct alias *next;
3343
3344         if (ap->flag & ALIASINUSE) {
3345                 ap->flag |= ALIASDEAD;
3346                 return ap;
3347         }
3348
3349         next = ap->next;
3350         free(ap->name);
3351         free(ap->val);
3352         free(ap);
3353         return next;
3354 }
3355
3356 static void
3357 setalias(const char *name, const char *val)
3358 {
3359         struct alias *ap, **app;
3360
3361         app = __lookupalias(name);
3362         ap = *app;
3363         INT_OFF;
3364         if (ap) {
3365                 if (!(ap->flag & ALIASINUSE)) {
3366                         free(ap->val);
3367                 }
3368                 ap->val = ckstrdup(val);
3369                 ap->flag &= ~ALIASDEAD;
3370         } else {
3371                 /* not found */
3372                 ap = ckzalloc(sizeof(struct alias));
3373                 ap->name = ckstrdup(name);
3374                 ap->val = ckstrdup(val);
3375                 /*ap->flag = 0; - ckzalloc did it */
3376                 /*ap->next = NULL;*/
3377                 *app = ap;
3378         }
3379         INT_ON;
3380 }
3381
3382 static int
3383 unalias(const char *name)
3384 {
3385         struct alias **app;
3386
3387         app = __lookupalias(name);
3388
3389         if (*app) {
3390                 INT_OFF;
3391                 *app = freealias(*app);
3392                 INT_ON;
3393                 return 0;
3394         }
3395
3396         return 1;
3397 }
3398
3399 static void
3400 rmaliases(void)
3401 {
3402         struct alias *ap, **app;
3403         int i;
3404
3405         INT_OFF;
3406         for (i = 0; i < ATABSIZE; i++) {
3407                 app = &atab[i];
3408                 for (ap = *app; ap; ap = *app) {
3409                         *app = freealias(*app);
3410                         if (ap == *app) {
3411                                 app = &ap->next;
3412                         }
3413                 }
3414         }
3415         INT_ON;
3416 }
3417
3418 static void
3419 printalias(const struct alias *ap)
3420 {
3421         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3422 }
3423
3424 /*
3425  * TODO - sort output
3426  */
3427 static int FAST_FUNC
3428 aliascmd(int argc UNUSED_PARAM, char **argv)
3429 {
3430         char *n, *v;
3431         int ret = 0;
3432         struct alias *ap;
3433
3434         if (!argv[1]) {
3435                 int i;
3436
3437                 for (i = 0; i < ATABSIZE; i++) {
3438                         for (ap = atab[i]; ap; ap = ap->next) {
3439                                 printalias(ap);
3440                         }
3441                 }
3442                 return 0;
3443         }
3444         while ((n = *++argv) != NULL) {
3445                 v = strchr(n+1, '=');
3446                 if (v == NULL) { /* n+1: funny ksh stuff */
3447                         ap = *__lookupalias(n);
3448                         if (ap == NULL) {
3449                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3450                                 ret = 1;
3451                         } else
3452                                 printalias(ap);
3453                 } else {
3454                         *v++ = '\0';
3455                         setalias(n, v);
3456                 }
3457         }
3458
3459         return ret;
3460 }
3461
3462 static int FAST_FUNC
3463 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3464 {
3465         int i;
3466
3467         while (nextopt("a") != '\0') {
3468                 rmaliases();
3469                 return 0;
3470         }
3471         for (i = 0; *argptr; argptr++) {
3472                 if (unalias(*argptr)) {
3473                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3474                         i = 1;
3475                 }
3476         }
3477
3478         return i;
3479 }
3480
3481 #endif /* ASH_ALIAS */
3482
3483
3484 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3485 #define FORK_FG    0
3486 #define FORK_BG    1
3487 #define FORK_NOJOB 2
3488
3489 /* mode flags for showjob(s) */
3490 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3491 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3492 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3493 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3494
3495 /*
3496  * A job structure contains information about a job.  A job is either a
3497  * single process or a set of processes contained in a pipeline.  In the
3498  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3499  * array of pids.
3500  */
3501 struct procstat {
3502         pid_t   ps_pid;         /* process id */
3503         int     ps_status;      /* last process status from wait() */
3504         char    *ps_cmd;        /* text of command being run */
3505 };
3506
3507 struct job {
3508         struct procstat ps0;    /* status of process */
3509         struct procstat *ps;    /* status or processes when more than one */
3510 #if JOBS
3511         int stopstatus;         /* status of a stopped job */
3512 #endif
3513         unsigned nprocs;        /* number of processes */
3514
3515 #define JOBRUNNING      0       /* at least one proc running */
3516 #define JOBSTOPPED      1       /* all procs are stopped */
3517 #define JOBDONE         2       /* all procs are completed */
3518         unsigned
3519                 state: 8,
3520 #if JOBS
3521                 sigint: 1,      /* job was killed by SIGINT */
3522                 jobctl: 1,      /* job running under job control */
3523 #endif
3524                 waited: 1,      /* true if this entry has been waited for */
3525                 used: 1,        /* true if this entry is in used */
3526                 changed: 1;     /* true if status has changed */
3527         struct job *prev_job;   /* previous job */
3528 };
3529
3530 static struct job *makejob(/*union node *,*/ int);
3531 static int forkshell(struct job *, union node *, int);
3532 static int waitforjob(struct job *);
3533
3534 #if !JOBS
3535 enum { doing_jobctl = 0 };
3536 #define setjobctl(on) do {} while (0)
3537 #else
3538 static smallint doing_jobctl; //references:8
3539 static void setjobctl(int);
3540 #endif
3541
3542 /*
3543  * Ignore a signal.
3544  */
3545 static void
3546 ignoresig(int signo)
3547 {
3548         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3549         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3550                 /* No, need to do it */
3551                 signal(signo, SIG_IGN);
3552         }
3553         sigmode[signo - 1] = S_HARD_IGN;
3554 }
3555
3556 /*
3557  * Only one usage site - in setsignal()
3558  */
3559 static void
3560 signal_handler(int signo)
3561 {
3562         if (signo == SIGCHLD) {
3563                 got_sigchld = 1;
3564                 if (!trap[SIGCHLD])
3565                         return;
3566         }
3567
3568         gotsig[signo - 1] = 1;
3569         pending_sig = signo;
3570
3571         if (signo == SIGINT && !trap[SIGINT]) {
3572                 if (!suppress_int) {
3573                         pending_sig = 0;
3574                         raise_interrupt(); /* does not return */
3575                 }
3576                 pending_int = 1;
3577         }
3578 }
3579
3580 /*
3581  * Set the signal handler for the specified signal.  The routine figures
3582  * out what it should be set to.
3583  */
3584 static void
3585 setsignal(int signo)
3586 {
3587         char *t;
3588         char cur_act, new_act;
3589         struct sigaction act;
3590
3591         t = trap[signo];
3592         new_act = S_DFL;
3593         if (t != NULL) { /* trap for this sig is set */
3594                 new_act = S_CATCH;
3595                 if (t[0] == '\0') /* trap is "": ignore this sig */
3596                         new_act = S_IGN;
3597         }
3598
3599         if (rootshell && new_act == S_DFL) {
3600                 switch (signo) {
3601                 case SIGINT:
3602                         if (iflag || minusc || sflag == 0)
3603                                 new_act = S_CATCH;
3604                         break;
3605                 case SIGQUIT:
3606 #if DEBUG
3607                         if (debug)
3608                                 break;
3609 #endif
3610                         /* man bash:
3611                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3612                          * commands run by bash have signal handlers
3613                          * set to the values inherited by the shell
3614                          * from its parent". */
3615                         new_act = S_IGN;
3616                         break;
3617                 case SIGTERM:
3618                         if (iflag)
3619                                 new_act = S_IGN;
3620                         break;
3621 #if JOBS
3622                 case SIGTSTP:
3623                 case SIGTTOU:
3624                         if (mflag)
3625                                 new_act = S_IGN;
3626                         break;
3627 #endif
3628                 }
3629         }
3630         /* if !rootshell, we reset SIGQUIT to DFL,
3631          * whereas we have to restore it to what shell got on entry.
3632          * This is handled by the fact that if signal was IGNored on entry,
3633          * then cur_act is S_HARD_IGN and we never change its sigaction
3634          * (see code below).
3635          */
3636
3637         if (signo == SIGCHLD)
3638                 new_act = S_CATCH;
3639
3640         t = &sigmode[signo - 1];
3641         cur_act = *t;
3642         if (cur_act == 0) {
3643                 /* current setting is not yet known */
3644                 if (sigaction(signo, NULL, &act)) {
3645                         /* pretend it worked; maybe we should give a warning,
3646                          * but other shells don't. We don't alter sigmode,
3647                          * so we retry every time.
3648                          * btw, in Linux it never fails. --vda */
3649                         return;
3650                 }
3651                 if (act.sa_handler == SIG_IGN) {
3652                         cur_act = S_HARD_IGN;
3653                         if (mflag
3654                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3655                         ) {
3656                                 cur_act = S_IGN;   /* don't hard ignore these */
3657                         }
3658                 }
3659                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3660                         /* installing SIG_DFL over SIG_DFL is a no-op */
3661                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3662                         *t = S_DFL;
3663                         return;
3664                 }
3665         }
3666         if (cur_act == S_HARD_IGN || cur_act == new_act)
3667                 return;
3668
3669         *t = new_act;
3670
3671         act.sa_handler = SIG_DFL;
3672         switch (new_act) {
3673         case S_CATCH:
3674                 act.sa_handler = signal_handler;
3675                 break;
3676         case S_IGN:
3677                 act.sa_handler = SIG_IGN;
3678                 break;
3679         }
3680         /* flags and mask matter only if !DFL and !IGN, but we do it
3681          * for all cases for more deterministic behavior:
3682          */
3683         act.sa_flags = 0; //TODO: why not SA_RESTART?
3684         sigfillset(&act.sa_mask);
3685
3686         sigaction_set(signo, &act);
3687 }
3688
3689 /* mode flags for set_curjob */
3690 #define CUR_DELETE 2
3691 #define CUR_RUNNING 1
3692 #define CUR_STOPPED 0
3693
3694 #if JOBS
3695 /* pgrp of shell on invocation */
3696 static int initialpgrp; //references:2
3697 static int ttyfd = -1; //5
3698 #endif
3699 /* array of jobs */
3700 static struct job *jobtab; //5
3701 /* size of array */
3702 static unsigned njobs; //4
3703 /* current job */
3704 static struct job *curjob; //lots
3705 /* number of presumed living untracked jobs */
3706 static int jobless; //4
3707
3708 #if 0
3709 /* Bash has a feature: it restores termios after a successful wait for
3710  * a foreground job which had at least one stopped or sigkilled member.
3711  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3712  * properly restoring tty state. Should we do this too?
3713  * A reproducer: ^Z an interactive python:
3714  *
3715  * # python
3716  * Python 2.7.12 (...)
3717  * >>> ^Z
3718  *      { python leaves tty in -icanon -echo state. We do survive that... }
3719  *  [1]+  Stopped                    python
3720  *      { ...however, next program (python #2) does not survive it well: }
3721  * # python
3722  * Python 2.7.12 (...)
3723  * >>> Traceback (most recent call last):
3724  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3725  *   File "<stdin>", line 1, in <module>
3726  * NameError: name 'qwerty' is not defined
3727  *
3728  * The implementation below is modeled on bash code and seems to work.
3729  * However, I'm not sure we should do this. For one: what if I'd fg
3730  * the stopped python instead? It'll be confused by "restored" tty state.
3731  */
3732 static struct termios shell_tty_info;
3733 static void
3734 get_tty_state(void)
3735 {
3736         if (rootshell && ttyfd >= 0)
3737                 tcgetattr(ttyfd, &shell_tty_info);
3738 }
3739 static void
3740 set_tty_state(void)
3741 {
3742         /* if (rootshell) - caller ensures this */
3743         if (ttyfd >= 0)
3744                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3745 }
3746 static int
3747 job_signal_status(struct job *jp)
3748 {
3749         int status;
3750         unsigned i;
3751         struct procstat *ps = jp->ps;
3752         for (i = 0; i < jp->nprocs; i++) {
3753                 status = ps[i].ps_status;
3754                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3755                         return status;
3756         }
3757         return 0;
3758 }
3759 static void
3760 restore_tty_if_stopped_or_signaled(struct job *jp)
3761 {
3762 //TODO: check what happens if we come from waitforjob() in expbackq()
3763         if (rootshell) {
3764                 int s = job_signal_status(jp);
3765                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3766                         set_tty_state();
3767         }
3768 }
3769 #else
3770 # define get_tty_state() ((void)0)
3771 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3772 #endif
3773
3774 static void
3775 set_curjob(struct job *jp, unsigned mode)
3776 {
3777         struct job *jp1;
3778         struct job **jpp, **curp;
3779
3780         /* first remove from list */
3781         jpp = curp = &curjob;
3782         while (1) {
3783                 jp1 = *jpp;
3784                 if (jp1 == jp)
3785                         break;
3786                 jpp = &jp1->prev_job;
3787         }
3788         *jpp = jp1->prev_job;
3789
3790         /* Then re-insert in correct position */
3791         jpp = curp;
3792         switch (mode) {
3793         default:
3794 #if DEBUG
3795                 abort();
3796 #endif
3797         case CUR_DELETE:
3798                 /* job being deleted */
3799                 break;
3800         case CUR_RUNNING:
3801                 /* newly created job or backgrounded job,
3802                  * put after all stopped jobs.
3803                  */
3804                 while (1) {
3805                         jp1 = *jpp;
3806 #if JOBS
3807                         if (!jp1 || jp1->state != JOBSTOPPED)
3808 #endif
3809                                 break;
3810                         jpp = &jp1->prev_job;
3811                 }
3812                 /* FALLTHROUGH */
3813 #if JOBS
3814         case CUR_STOPPED:
3815 #endif
3816                 /* newly stopped job - becomes curjob */
3817                 jp->prev_job = *jpp;
3818                 *jpp = jp;
3819                 break;
3820         }
3821 }
3822
3823 #if JOBS || DEBUG
3824 static int
3825 jobno(const struct job *jp)
3826 {
3827         return jp - jobtab + 1;
3828 }
3829 #endif
3830
3831 /*
3832  * Convert a job name to a job structure.
3833  */
3834 #if !JOBS
3835 #define getjob(name, getctl) getjob(name)
3836 #endif
3837 static struct job *
3838 getjob(const char *name, int getctl)
3839 {
3840         struct job *jp;
3841         struct job *found;
3842         const char *err_msg = "%s: no such job";
3843         unsigned num;
3844         int c;
3845         const char *p;
3846         char *(*match)(const char *, const char *);
3847
3848         jp = curjob;
3849         p = name;
3850         if (!p)
3851                 goto currentjob;
3852
3853         if (*p != '%')
3854                 goto err;
3855
3856         c = *++p;
3857         if (!c)
3858                 goto currentjob;
3859
3860         if (!p[1]) {
3861                 if (c == '+' || c == '%') {
3862  currentjob:
3863                         err_msg = "No current job";
3864                         goto check;
3865                 }
3866                 if (c == '-') {
3867                         if (jp)
3868                                 jp = jp->prev_job;
3869                         err_msg = "No previous job";
3870  check:
3871                         if (!jp)
3872                                 goto err;
3873                         goto gotit;
3874                 }
3875         }
3876
3877         if (is_number(p)) {
3878                 num = atoi(p);
3879                 if (num > 0 && num <= njobs) {
3880                         jp = jobtab + num - 1;
3881                         if (jp->used)
3882                                 goto gotit;
3883                         goto err;
3884                 }
3885         }
3886
3887         match = prefix;
3888         if (*p == '?') {
3889                 match = strstr;
3890                 p++;
3891         }
3892
3893         found = NULL;
3894         while (jp) {
3895                 if (match(jp->ps[0].ps_cmd, p)) {
3896                         if (found)
3897                                 goto err;
3898                         found = jp;
3899                         err_msg = "%s: ambiguous";
3900                 }
3901                 jp = jp->prev_job;
3902         }
3903         if (!found)
3904                 goto err;
3905         jp = found;
3906
3907  gotit:
3908 #if JOBS
3909         err_msg = "job %s not created under job control";
3910         if (getctl && jp->jobctl == 0)
3911                 goto err;
3912 #endif
3913         return jp;
3914  err:
3915         ash_msg_and_raise_error(err_msg, name);
3916 }
3917
3918 /*
3919  * Mark a job structure as unused.
3920  */
3921 static void
3922 freejob(struct job *jp)
3923 {
3924         struct procstat *ps;
3925         int i;
3926
3927         INT_OFF;
3928         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3929                 if (ps->ps_cmd != nullstr)
3930                         free(ps->ps_cmd);
3931         }
3932         if (jp->ps != &jp->ps0)
3933                 free(jp->ps);
3934         jp->used = 0;
3935         set_curjob(jp, CUR_DELETE);
3936         INT_ON;
3937 }
3938
3939 #if JOBS
3940 static void
3941 xtcsetpgrp(int fd, pid_t pgrp)
3942 {
3943         if (tcsetpgrp(fd, pgrp))
3944                 ash_msg_and_raise_perror("can't set tty process group");
3945 }
3946
3947 /*
3948  * Turn job control on and off.
3949  *
3950  * Note:  This code assumes that the third arg to ioctl is a character
3951  * pointer, which is true on Berkeley systems but not System V.  Since
3952  * System V doesn't have job control yet, this isn't a problem now.
3953  *
3954  * Called with interrupts off.
3955  */
3956 static void
3957 setjobctl(int on)
3958 {
3959         int fd;
3960         int pgrp;
3961
3962         if (on == doing_jobctl || rootshell == 0)
3963                 return;
3964         if (on) {
3965                 int ofd;
3966                 ofd = fd = open(_PATH_TTY, O_RDWR);
3967                 if (fd < 0) {
3968         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3969          * That sometimes helps to acquire controlling tty.
3970          * Obviously, a workaround for bugs when someone
3971          * failed to provide a controlling tty to bash! :) */
3972                         fd = 2;
3973                         while (!isatty(fd))
3974                                 if (--fd < 0)
3975                                         goto out;
3976                 }
3977                 /* fd is a tty at this point */
3978                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
3979                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3980                         close(ofd);
3981                 if (fd < 0)
3982                         goto out; /* F_DUPFD failed */
3983                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
3984                         close_on_exec_on(fd);
3985                 while (1) { /* while we are in the background */
3986                         pgrp = tcgetpgrp(fd);
3987                         if (pgrp < 0) {
3988  out:
3989                                 ash_msg("can't access tty; job control turned off");
3990                                 mflag = on = 0;
3991                                 goto close;
3992                         }
3993                         if (pgrp == getpgrp())
3994                                 break;
3995                         killpg(0, SIGTTIN);
3996                 }
3997                 initialpgrp = pgrp;
3998
3999                 setsignal(SIGTSTP);
4000                 setsignal(SIGTTOU);
4001                 setsignal(SIGTTIN);
4002                 pgrp = rootpid;
4003                 setpgid(0, pgrp);
4004                 xtcsetpgrp(fd, pgrp);
4005         } else {
4006                 /* turning job control off */
4007                 fd = ttyfd;
4008                 pgrp = initialpgrp;
4009                 /* was xtcsetpgrp, but this can make exiting ash
4010                  * loop forever if pty is already deleted */
4011                 tcsetpgrp(fd, pgrp);
4012                 setpgid(0, pgrp);
4013                 setsignal(SIGTSTP);
4014                 setsignal(SIGTTOU);
4015                 setsignal(SIGTTIN);
4016  close:
4017                 if (fd >= 0)
4018                         close(fd);
4019                 fd = -1;
4020         }
4021         ttyfd = fd;
4022         doing_jobctl = on;
4023 }
4024
4025 static int FAST_FUNC
4026 killcmd(int argc, char **argv)
4027 {
4028         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4029                 int i = 1;
4030                 do {
4031                         if (argv[i][0] == '%') {
4032                                 /*
4033                                  * "kill %N" - job kill
4034                                  * Converting to pgrp / pid kill
4035                                  */
4036                                 struct job *jp;
4037                                 char *dst;
4038                                 int j, n;
4039
4040                                 jp = getjob(argv[i], 0);
4041                                 /*
4042                                  * In jobs started under job control, we signal
4043                                  * entire process group by kill -PGRP_ID.
4044                                  * This happens, f.e., in interactive shell.
4045                                  *
4046                                  * Otherwise, we signal each child via
4047                                  * kill PID1 PID2 PID3.
4048                                  * Testcases:
4049                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4050                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4051                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4052                                  */
4053                                 n = jp->nprocs; /* can't be 0 (I hope) */
4054                                 if (jp->jobctl)
4055                                         n = 1;
4056                                 dst = alloca(n * sizeof(int)*4);
4057                                 argv[i] = dst;
4058                                 for (j = 0; j < n; j++) {
4059                                         struct procstat *ps = &jp->ps[j];
4060                                         /* Skip non-running and not-stopped members
4061                                          * (i.e. dead members) of the job
4062                                          */
4063                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4064                                                 continue;
4065                                         /*
4066                                          * kill_main has matching code to expect
4067                                          * leading space. Needed to not confuse
4068                                          * negative pids with "kill -SIGNAL_NO" syntax
4069                                          */
4070                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4071                                 }
4072                                 *dst = '\0';
4073                         }
4074                 } while (argv[++i]);
4075         }
4076         return kill_main(argc, argv);
4077 }
4078
4079 static void
4080 showpipe(struct job *jp /*, FILE *out*/)
4081 {
4082         struct procstat *ps;
4083         struct procstat *psend;
4084
4085         psend = jp->ps + jp->nprocs;
4086         for (ps = jp->ps + 1; ps < psend; ps++)
4087                 printf(" | %s", ps->ps_cmd);
4088         newline_and_flush(stdout);
4089         flush_stdout_stderr();
4090 }
4091
4092
4093 static int
4094 restartjob(struct job *jp, int mode)
4095 {
4096         struct procstat *ps;
4097         int i;
4098         int status;
4099         pid_t pgid;
4100
4101         INT_OFF;
4102         if (jp->state == JOBDONE)
4103                 goto out;
4104         jp->state = JOBRUNNING;
4105         pgid = jp->ps[0].ps_pid;
4106         if (mode == FORK_FG) {
4107                 get_tty_state();
4108                 xtcsetpgrp(ttyfd, pgid);
4109         }
4110         killpg(pgid, SIGCONT);
4111         ps = jp->ps;
4112         i = jp->nprocs;
4113         do {
4114                 if (WIFSTOPPED(ps->ps_status)) {
4115                         ps->ps_status = -1;
4116                 }
4117                 ps++;
4118         } while (--i);
4119  out:
4120         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4121         INT_ON;
4122         return status;
4123 }
4124
4125 static int FAST_FUNC
4126 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4127 {
4128         struct job *jp;
4129         int mode;
4130         int retval;
4131
4132         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4133         nextopt(nullstr);
4134         argv = argptr;
4135         do {
4136                 jp = getjob(*argv, 1);
4137                 if (mode == FORK_BG) {
4138                         set_curjob(jp, CUR_RUNNING);
4139                         printf("[%d] ", jobno(jp));
4140                 }
4141                 out1str(jp->ps[0].ps_cmd);
4142                 showpipe(jp /*, stdout*/);
4143                 retval = restartjob(jp, mode);
4144         } while (*argv && *++argv);
4145         return retval;
4146 }
4147 #endif
4148
4149 static int
4150 sprint_status48(char *s, int status, int sigonly)
4151 {
4152         int col;
4153         int st;
4154
4155         col = 0;
4156         if (!WIFEXITED(status)) {
4157 #if JOBS
4158                 if (WIFSTOPPED(status))
4159                         st = WSTOPSIG(status);
4160                 else
4161 #endif
4162                         st = WTERMSIG(status);
4163                 if (sigonly) {
4164                         if (st == SIGINT || st == SIGPIPE)
4165                                 goto out;
4166 #if JOBS
4167                         if (WIFSTOPPED(status))
4168                                 goto out;
4169 #endif
4170                 }
4171                 st &= 0x7f;
4172 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4173                 col = fmtstr(s, 32, strsignal(st));
4174                 if (WCOREDUMP(status)) {
4175                         strcpy(s + col, " (core dumped)");
4176                         col += sizeof(" (core dumped)")-1;
4177                 }
4178         } else if (!sigonly) {
4179                 st = WEXITSTATUS(status);
4180                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4181         }
4182  out:
4183         return col;
4184 }
4185
4186 static int
4187 wait_block_or_sig(int *status)
4188 {
4189         int pid;
4190
4191         do {
4192                 sigset_t mask;
4193
4194                 /* Poll all children for changes in their state */
4195                 got_sigchld = 0;
4196                 /* if job control is active, accept stopped processes too */
4197                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4198                 if (pid != 0)
4199                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4200
4201                 /* Children exist, but none are ready. Sleep until interesting signal */
4202 #if 1
4203                 sigfillset(&mask);
4204                 sigprocmask(SIG_SETMASK, &mask, &mask);
4205                 while (!got_sigchld && !pending_sig)
4206                         sigsuspend(&mask);
4207                 sigprocmask(SIG_SETMASK, &mask, NULL);
4208 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4209                 while (!got_sigchld && !pending_sig)
4210                         pause();
4211 #endif
4212
4213                 /* If it was SIGCHLD, poll children again */
4214         } while (got_sigchld);
4215
4216         return pid;
4217 }
4218
4219 #define DOWAIT_NONBLOCK 0
4220 #define DOWAIT_BLOCK    1
4221 #define DOWAIT_BLOCK_OR_SIG 2
4222
4223 static int
4224 dowait(int block, struct job *job)
4225 {
4226         int pid;
4227         int status;
4228         struct job *jp;
4229         struct job *thisjob = NULL;
4230
4231         TRACE(("dowait(0x%x) called\n", block));
4232
4233         /* It's wrong to call waitpid() outside of INT_OFF region:
4234          * signal can arrive just after syscall return and handler can
4235          * longjmp away, losing stop/exit notification processing.
4236          * Thus, for "jobs" builtin, and for waiting for a fg job,
4237          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4238          *
4239          * However, for "wait" builtin it is wrong to simply call waitpid()
4240          * in INT_OFF region: "wait" needs to wait for any running job
4241          * to change state, but should exit on any trap too.
4242          * In INT_OFF region, a signal just before syscall entry can set
4243          * pending_sig variables, but we can't check them, and we would
4244          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4245          *
4246          * Because of this, we run inside INT_OFF, but use a special routine
4247          * which combines waitpid() and sigsuspend().
4248          * This is the reason why we need to have a handler for SIGCHLD:
4249          * SIG_DFL handler does not wake sigsuspend().
4250          */
4251         INT_OFF;
4252         if (block == DOWAIT_BLOCK_OR_SIG) {
4253                 pid = wait_block_or_sig(&status);
4254         } else {
4255                 int wait_flags = 0;
4256                 if (block == DOWAIT_NONBLOCK)
4257                         wait_flags = WNOHANG;
4258                 /* if job control is active, accept stopped processes too */
4259                 if (doing_jobctl)
4260                         wait_flags |= WUNTRACED;
4261                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4262                 pid = waitpid(-1, &status, wait_flags);
4263         }
4264         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4265                                 pid, status, errno, strerror(errno)));
4266         if (pid <= 0)
4267                 goto out;
4268
4269         thisjob = NULL;
4270         for (jp = curjob; jp; jp = jp->prev_job) {
4271                 int jobstate;
4272                 struct procstat *ps;
4273                 struct procstat *psend;
4274                 if (jp->state == JOBDONE)
4275                         continue;
4276                 jobstate = JOBDONE;
4277                 ps = jp->ps;
4278                 psend = ps + jp->nprocs;
4279                 do {
4280                         if (ps->ps_pid == pid) {
4281                                 TRACE(("Job %d: changing status of proc %d "
4282                                         "from 0x%x to 0x%x\n",
4283                                         jobno(jp), pid, ps->ps_status, status));
4284                                 ps->ps_status = status;
4285                                 thisjob = jp;
4286                         }
4287                         if (ps->ps_status == -1)
4288                                 jobstate = JOBRUNNING;
4289 #if JOBS
4290                         if (jobstate == JOBRUNNING)
4291                                 continue;
4292                         if (WIFSTOPPED(ps->ps_status)) {
4293                                 jp->stopstatus = ps->ps_status;
4294                                 jobstate = JOBSTOPPED;
4295                         }
4296 #endif
4297                 } while (++ps < psend);
4298                 if (!thisjob)
4299                         continue;
4300
4301                 /* Found the job where one of its processes changed its state.
4302                  * Is there at least one live and running process in this job? */
4303                 if (jobstate != JOBRUNNING) {
4304                         /* No. All live processes in the job are stopped
4305                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4306                          */
4307                         thisjob->changed = 1;
4308                         if (thisjob->state != jobstate) {
4309                                 TRACE(("Job %d: changing state from %d to %d\n",
4310                                         jobno(thisjob), thisjob->state, jobstate));
4311                                 thisjob->state = jobstate;
4312 #if JOBS
4313                                 if (jobstate == JOBSTOPPED)
4314                                         set_curjob(thisjob, CUR_STOPPED);
4315 #endif
4316                         }
4317                 }
4318                 goto out;
4319         }
4320         /* The process wasn't found in job list */
4321 #if JOBS
4322         if (!WIFSTOPPED(status))
4323                 jobless--;
4324 #endif
4325  out:
4326         INT_ON;
4327
4328         if (thisjob && thisjob == job) {
4329                 char s[48 + 1];
4330                 int len;
4331
4332                 len = sprint_status48(s, status, 1);
4333                 if (len) {
4334                         s[len] = '\n';
4335                         s[len + 1] = '\0';
4336                         out2str(s);
4337                 }
4338         }
4339         return pid;
4340 }
4341
4342 #if JOBS
4343 static void
4344 showjob(struct job *jp, int mode)
4345 {
4346         struct procstat *ps;
4347         struct procstat *psend;
4348         int col;
4349         int indent_col;
4350         char s[16 + 16 + 48];
4351         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4352
4353         ps = jp->ps;
4354
4355         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4356                 /* just output process (group) id of pipeline */
4357                 fprintf(out, "%d\n", ps->ps_pid);
4358                 return;
4359         }
4360
4361         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4362         indent_col = col;
4363
4364         if (jp == curjob)
4365                 s[col - 3] = '+';
4366         else if (curjob && jp == curjob->prev_job)
4367                 s[col - 3] = '-';
4368
4369         if (mode & SHOW_PIDS)
4370                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4371
4372         psend = ps + jp->nprocs;
4373
4374         if (jp->state == JOBRUNNING) {
4375                 strcpy(s + col, "Running");
4376                 col += sizeof("Running") - 1;
4377         } else {
4378                 int status = psend[-1].ps_status;
4379                 if (jp->state == JOBSTOPPED)
4380                         status = jp->stopstatus;
4381                 col += sprint_status48(s + col, status, 0);
4382         }
4383         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4384
4385         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4386          * or prints several "PID             | <cmdN>" lines,
4387          * depending on SHOW_PIDS bit.
4388          * We do not print status of individual processes
4389          * between PID and <cmdN>. bash does it, but not very well:
4390          * first line shows overall job status, not process status,
4391          * making it impossible to know 1st process status.
4392          */
4393         goto start;
4394         do {
4395                 /* for each process */
4396                 s[0] = '\0';
4397                 col = 33;
4398                 if (mode & SHOW_PIDS)
4399                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4400  start:
4401                 fprintf(out, "%s%*c%s%s",
4402                                 s,
4403                                 33 - col >= 0 ? 33 - col : 0, ' ',
4404                                 ps == jp->ps ? "" : "| ",
4405                                 ps->ps_cmd
4406                 );
4407         } while (++ps != psend);
4408         newline_and_flush(out);
4409
4410         jp->changed = 0;
4411
4412         if (jp->state == JOBDONE) {
4413                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4414                 freejob(jp);
4415         }
4416 }
4417
4418 /*
4419  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4420  * statuses have changed since the last call to showjobs.
4421  */
4422 static void
4423 showjobs(int mode)
4424 {
4425         struct job *jp;
4426
4427         TRACE(("showjobs(0x%x) called\n", mode));
4428
4429         /* Handle all finished jobs */
4430         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4431                 continue;
4432
4433         for (jp = curjob; jp; jp = jp->prev_job) {
4434                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4435                         showjob(jp, mode);
4436                 }
4437         }
4438 }
4439
4440 static int FAST_FUNC
4441 jobscmd(int argc UNUSED_PARAM, char **argv)
4442 {
4443         int mode, m;
4444
4445         mode = 0;
4446         while ((m = nextopt("lp")) != '\0') {
4447                 if (m == 'l')
4448                         mode |= SHOW_PIDS;
4449                 else
4450                         mode |= SHOW_ONLY_PGID;
4451         }
4452
4453         argv = argptr;
4454         if (*argv) {
4455                 do
4456                         showjob(getjob(*argv, 0), mode);
4457                 while (*++argv);
4458         } else {
4459                 showjobs(mode);
4460         }
4461
4462         return 0;
4463 }
4464 #endif /* JOBS */
4465
4466 /* Called only on finished or stopped jobs (no members are running) */
4467 static int
4468 getstatus(struct job *job)
4469 {
4470         int status;
4471         int retval;
4472         struct procstat *ps;
4473
4474         /* Fetch last member's status */
4475         ps = job->ps + job->nprocs - 1;
4476         status = ps->ps_status;
4477         if (pipefail) {
4478                 /* "set -o pipefail" mode: use last _nonzero_ status */
4479                 while (status == 0 && --ps >= job->ps)
4480                         status = ps->ps_status;
4481         }
4482
4483         retval = WEXITSTATUS(status);
4484         if (!WIFEXITED(status)) {
4485 #if JOBS
4486                 retval = WSTOPSIG(status);
4487                 if (!WIFSTOPPED(status))
4488 #endif
4489                 {
4490                         /* XXX: limits number of signals */
4491                         retval = WTERMSIG(status);
4492 #if JOBS
4493                         if (retval == SIGINT)
4494                                 job->sigint = 1;
4495 #endif
4496                 }
4497                 retval += 128;
4498         }
4499         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4500                 jobno(job), job->nprocs, status, retval));
4501         return retval;
4502 }
4503
4504 static int FAST_FUNC
4505 waitcmd(int argc UNUSED_PARAM, char **argv)
4506 {
4507         struct job *job;
4508         int retval;
4509         struct job *jp;
4510
4511         nextopt(nullstr);
4512         retval = 0;
4513
4514         argv = argptr;
4515         if (!*argv) {
4516                 /* wait for all jobs */
4517                 for (;;) {
4518                         jp = curjob;
4519                         while (1) {
4520                                 if (!jp) /* no running procs */
4521                                         goto ret;
4522                                 if (jp->state == JOBRUNNING)
4523                                         break;
4524                                 jp->waited = 1;
4525                                 jp = jp->prev_job;
4526                         }
4527         /* man bash:
4528          * "When bash is waiting for an asynchronous command via
4529          * the wait builtin, the reception of a signal for which a trap
4530          * has been set will cause the wait builtin to return immediately
4531          * with an exit status greater than 128, immediately after which
4532          * the trap is executed."
4533          */
4534                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4535         /* if child sends us a signal *and immediately exits*,
4536          * dowait() returns pid > 0. Check this case,
4537          * not "if (dowait() < 0)"!
4538          */
4539                         if (pending_sig)
4540                                 goto sigout;
4541                 }
4542         }
4543
4544         retval = 127;
4545         do {
4546                 if (**argv != '%') {
4547                         pid_t pid = number(*argv);
4548                         job = curjob;
4549                         while (1) {
4550                                 if (!job)
4551                                         goto repeat;
4552                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4553                                         break;
4554                                 job = job->prev_job;
4555                         }
4556                 } else {
4557                         job = getjob(*argv, 0);
4558                 }
4559                 /* loop until process terminated or stopped */
4560                 while (job->state == JOBRUNNING) {
4561                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4562                         if (pending_sig)
4563                                 goto sigout;
4564                 }
4565                 job->waited = 1;
4566                 retval = getstatus(job);
4567  repeat: ;
4568         } while (*++argv);
4569
4570  ret:
4571         return retval;
4572  sigout:
4573         retval = 128 + pending_sig;
4574         return retval;
4575 }
4576
4577 static struct job *
4578 growjobtab(void)
4579 {
4580         size_t len;
4581         ptrdiff_t offset;
4582         struct job *jp, *jq;
4583
4584         len = njobs * sizeof(*jp);
4585         jq = jobtab;
4586         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4587
4588         offset = (char *)jp - (char *)jq;
4589         if (offset) {
4590                 /* Relocate pointers */
4591                 size_t l = len;
4592
4593                 jq = (struct job *)((char *)jq + l);
4594                 while (l) {
4595                         l -= sizeof(*jp);
4596                         jq--;
4597 #define joff(p) ((struct job *)((char *)(p) + l))
4598 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4599                         if (joff(jp)->ps == &jq->ps0)
4600                                 jmove(joff(jp)->ps);
4601                         if (joff(jp)->prev_job)
4602                                 jmove(joff(jp)->prev_job);
4603                 }
4604                 if (curjob)
4605                         jmove(curjob);
4606 #undef joff
4607 #undef jmove
4608         }
4609
4610         njobs += 4;
4611         jobtab = jp;
4612         jp = (struct job *)((char *)jp + len);
4613         jq = jp + 3;
4614         do {
4615                 jq->used = 0;
4616         } while (--jq >= jp);
4617         return jp;
4618 }
4619
4620 /*
4621  * Return a new job structure.
4622  * Called with interrupts off.
4623  */
4624 static struct job *
4625 makejob(/*union node *node,*/ int nprocs)
4626 {
4627         int i;
4628         struct job *jp;
4629
4630         for (i = njobs, jp = jobtab; ; jp++) {
4631                 if (--i < 0) {
4632                         jp = growjobtab();
4633                         break;
4634                 }
4635                 if (jp->used == 0)
4636                         break;
4637                 if (jp->state != JOBDONE || !jp->waited)
4638                         continue;
4639 #if JOBS
4640                 if (doing_jobctl)
4641                         continue;
4642 #endif
4643                 freejob(jp);
4644                 break;
4645         }
4646         memset(jp, 0, sizeof(*jp));
4647 #if JOBS
4648         /* jp->jobctl is a bitfield.
4649          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4650         if (doing_jobctl)
4651                 jp->jobctl = 1;
4652 #endif
4653         jp->prev_job = curjob;
4654         curjob = jp;
4655         jp->used = 1;
4656         jp->ps = &jp->ps0;
4657         if (nprocs > 1) {
4658                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4659         }
4660         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4661                                 jobno(jp)));
4662         return jp;
4663 }
4664
4665 #if JOBS
4666 /*
4667  * Return a string identifying a command (to be printed by the
4668  * jobs command).
4669  */
4670 static char *cmdnextc;
4671
4672 static void
4673 cmdputs(const char *s)
4674 {
4675         static const char vstype[VSTYPE + 1][3] = {
4676                 "", "}", "-", "+", "?", "=",
4677                 "%", "%%", "#", "##"
4678                 IF_BASH_SUBSTR(, ":")
4679                 IF_BASH_PATTERN_SUBST(, "/", "//")
4680         };
4681
4682         const char *p, *str;
4683         char cc[2];
4684         char *nextc;
4685         unsigned char c;
4686         unsigned char subtype = 0;
4687         int quoted = 0;
4688
4689         cc[1] = '\0';
4690         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4691         p = s;
4692         while ((c = *p++) != '\0') {
4693                 str = NULL;
4694                 switch (c) {
4695                 case CTLESC:
4696                         c = *p++;
4697                         break;
4698                 case CTLVAR:
4699                         subtype = *p++;
4700                         if ((subtype & VSTYPE) == VSLENGTH)
4701                                 str = "${#";
4702                         else
4703                                 str = "${";
4704                         goto dostr;
4705                 case CTLENDVAR:
4706                         str = "\"}" + !(quoted & 1);
4707                         quoted >>= 1;
4708                         subtype = 0;
4709                         goto dostr;
4710                 case CTLBACKQ:
4711                         str = "$(...)";
4712                         goto dostr;
4713 #if ENABLE_FEATURE_SH_MATH
4714                 case CTLARI:
4715                         str = "$((";
4716                         goto dostr;
4717                 case CTLENDARI:
4718                         str = "))";
4719                         goto dostr;
4720 #endif
4721                 case CTLQUOTEMARK:
4722                         quoted ^= 1;
4723                         c = '"';
4724                         break;
4725                 case '=':
4726                         if (subtype == 0)
4727                                 break;
4728                         if ((subtype & VSTYPE) != VSNORMAL)
4729                                 quoted <<= 1;
4730                         str = vstype[subtype & VSTYPE];
4731                         if (subtype & VSNUL)
4732                                 c = ':';
4733                         else
4734                                 goto checkstr;
4735                         break;
4736                 case '\'':
4737                 case '\\':
4738                 case '"':
4739                 case '$':
4740                         /* These can only happen inside quotes */
4741                         cc[0] = c;
4742                         str = cc;
4743 //FIXME:
4744 // $ true $$ &
4745 // $ <cr>
4746 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4747                         c = '\\';
4748                         break;
4749                 default:
4750                         break;
4751                 }
4752                 USTPUTC(c, nextc);
4753  checkstr:
4754                 if (!str)
4755                         continue;
4756  dostr:
4757                 while ((c = *str++) != '\0') {
4758                         USTPUTC(c, nextc);
4759                 }
4760         } /* while *p++ not NUL */
4761
4762         if (quoted & 1) {
4763                 USTPUTC('"', nextc);
4764         }
4765         *nextc = 0;
4766         cmdnextc = nextc;
4767 }
4768
4769 /* cmdtxt() and cmdlist() call each other */
4770 static void cmdtxt(union node *n);
4771
4772 static void
4773 cmdlist(union node *np, int sep)
4774 {
4775         for (; np; np = np->narg.next) {
4776                 if (!sep)
4777                         cmdputs(" ");
4778                 cmdtxt(np);
4779                 if (sep && np->narg.next)
4780                         cmdputs(" ");
4781         }
4782 }
4783
4784 static void
4785 cmdtxt(union node *n)
4786 {
4787         union node *np;
4788         struct nodelist *lp;
4789         const char *p;
4790
4791         if (!n)
4792                 return;
4793         switch (n->type) {
4794         default:
4795 #if DEBUG
4796                 abort();
4797 #endif
4798         case NPIPE:
4799                 lp = n->npipe.cmdlist;
4800                 for (;;) {
4801                         cmdtxt(lp->n);
4802                         lp = lp->next;
4803                         if (!lp)
4804                                 break;
4805                         cmdputs(" | ");
4806                 }
4807                 break;
4808         case NSEMI:
4809                 p = "; ";
4810                 goto binop;
4811         case NAND:
4812                 p = " && ";
4813                 goto binop;
4814         case NOR:
4815                 p = " || ";
4816  binop:
4817                 cmdtxt(n->nbinary.ch1);
4818                 cmdputs(p);
4819                 n = n->nbinary.ch2;
4820                 goto donode;
4821         case NREDIR:
4822         case NBACKGND:
4823                 n = n->nredir.n;
4824                 goto donode;
4825         case NNOT:
4826                 cmdputs("!");
4827                 n = n->nnot.com;
4828  donode:
4829                 cmdtxt(n);
4830                 break;
4831         case NIF:
4832                 cmdputs("if ");
4833                 cmdtxt(n->nif.test);
4834                 cmdputs("; then ");
4835                 if (n->nif.elsepart) {
4836                         cmdtxt(n->nif.ifpart);
4837                         cmdputs("; else ");
4838                         n = n->nif.elsepart;
4839                 } else {
4840                         n = n->nif.ifpart;
4841                 }
4842                 p = "; fi";
4843                 goto dotail;
4844         case NSUBSHELL:
4845                 cmdputs("(");
4846                 n = n->nredir.n;
4847                 p = ")";
4848                 goto dotail;
4849         case NWHILE:
4850                 p = "while ";
4851                 goto until;
4852         case NUNTIL:
4853                 p = "until ";
4854  until:
4855                 cmdputs(p);
4856                 cmdtxt(n->nbinary.ch1);
4857                 n = n->nbinary.ch2;
4858                 p = "; done";
4859  dodo:
4860                 cmdputs("; do ");
4861  dotail:
4862                 cmdtxt(n);
4863                 goto dotail2;
4864         case NFOR:
4865                 cmdputs("for ");
4866                 cmdputs(n->nfor.var);
4867                 cmdputs(" in ");
4868                 cmdlist(n->nfor.args, 1);
4869                 n = n->nfor.body;
4870                 p = "; done";
4871                 goto dodo;
4872         case NDEFUN:
4873                 cmdputs(n->ndefun.text);
4874                 p = "() { ... }";
4875                 goto dotail2;
4876         case NCMD:
4877                 cmdlist(n->ncmd.args, 1);
4878                 cmdlist(n->ncmd.redirect, 0);
4879                 break;
4880         case NARG:
4881                 p = n->narg.text;
4882  dotail2:
4883                 cmdputs(p);
4884                 break;
4885         case NHERE:
4886         case NXHERE:
4887                 p = "<<...";
4888                 goto dotail2;
4889         case NCASE:
4890                 cmdputs("case ");
4891                 cmdputs(n->ncase.expr->narg.text);
4892                 cmdputs(" in ");
4893                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4894                         cmdtxt(np->nclist.pattern);
4895                         cmdputs(") ");
4896                         cmdtxt(np->nclist.body);
4897                         cmdputs(";; ");
4898                 }
4899                 p = "esac";
4900                 goto dotail2;
4901         case NTO:
4902                 p = ">";
4903                 goto redir;
4904         case NCLOBBER:
4905                 p = ">|";
4906                 goto redir;
4907         case NAPPEND:
4908                 p = ">>";
4909                 goto redir;
4910 #if BASH_REDIR_OUTPUT
4911         case NTO2:
4912 #endif
4913         case NTOFD:
4914                 p = ">&";
4915                 goto redir;
4916         case NFROM:
4917                 p = "<";
4918                 goto redir;
4919         case NFROMFD:
4920                 p = "<&";
4921                 goto redir;
4922         case NFROMTO:
4923                 p = "<>";
4924  redir:
4925                 cmdputs(utoa(n->nfile.fd));
4926                 cmdputs(p);
4927                 if (n->type == NTOFD || n->type == NFROMFD) {
4928                         if (n->ndup.dupfd >= 0)
4929                                 cmdputs(utoa(n->ndup.dupfd));
4930                         else
4931                                 cmdputs("-");
4932                         break;
4933                 }
4934                 n = n->nfile.fname;
4935                 goto donode;
4936         }
4937 }
4938
4939 static char *
4940 commandtext(union node *n)
4941 {
4942         char *name;
4943
4944         STARTSTACKSTR(cmdnextc);
4945         cmdtxt(n);
4946         name = stackblock();
4947         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4948         return ckstrdup(name);
4949 }
4950 #endif /* JOBS */
4951
4952 /*
4953  * Fork off a subshell.  If we are doing job control, give the subshell its
4954  * own process group.  Jp is a job structure that the job is to be added to.
4955  * N is the command that will be evaluated by the child.  Both jp and n may
4956  * be NULL.  The mode parameter can be one of the following:
4957  *      FORK_FG - Fork off a foreground process.
4958  *      FORK_BG - Fork off a background process.
4959  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4960  *                   process group even if job control is on.
4961  *
4962  * When job control is turned off, background processes have their standard
4963  * input redirected to /dev/null (except for the second and later processes
4964  * in a pipeline).
4965  *
4966  * Called with interrupts off.
4967  */
4968 /*
4969  * Clear traps on a fork.
4970  */
4971 static void
4972 clear_traps(void)
4973 {
4974         char **tp;
4975
4976         INT_OFF;
4977         for (tp = trap; tp < &trap[NSIG]; tp++) {
4978                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4979                         if (trap_ptr == trap)
4980                                 free(*tp);
4981                         /* else: it "belongs" to trap_ptr vector, don't free */
4982                         *tp = NULL;
4983                         if ((tp - trap) != 0)
4984                                 setsignal(tp - trap);
4985                 }
4986         }
4987         may_have_traps = 0;
4988         INT_ON;
4989 }
4990
4991 /* Lives far away from here, needed for forkchild */
4992 static void closescript(void);
4993
4994 /* Called after fork(), in child */
4995 /* jp and n are NULL when called by openhere() for heredoc support */
4996 static NOINLINE void
4997 forkchild(struct job *jp, union node *n, int mode)
4998 {
4999         int oldlvl;
5000
5001         TRACE(("Child shell %d\n", getpid()));
5002         oldlvl = shlvl;
5003         shlvl++;
5004
5005         /* man bash: "Non-builtin commands run by bash have signal handlers
5006          * set to the values inherited by the shell from its parent".
5007          * Do we do it correctly? */
5008
5009         closescript();
5010
5011         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5012          && n && n->type == NCMD        /* is it single cmd? */
5013         /* && n->ncmd.args->type == NARG - always true? */
5014          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5015          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5016         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5017         ) {
5018                 TRACE(("Trap hack\n"));
5019                 /* Awful hack for `trap` or $(trap).
5020                  *
5021                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5022                  * contains an example where "trap" is executed in a subshell:
5023                  *
5024                  * save_traps=$(trap)
5025                  * ...
5026                  * eval "$save_traps"
5027                  *
5028                  * Standard does not say that "trap" in subshell shall print
5029                  * parent shell's traps. It only says that its output
5030                  * must have suitable form, but then, in the above example
5031                  * (which is not supposed to be normative), it implies that.
5032                  *
5033                  * bash (and probably other shell) does implement it
5034                  * (traps are reset to defaults, but "trap" still shows them),
5035                  * but as a result, "trap" logic is hopelessly messed up:
5036                  *
5037                  * # trap
5038                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5039                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5040                  * # true | trap   <--- trap is in subshell - no output (ditto)
5041                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5042                  * trap -- 'echo Ho' SIGWINCH
5043                  * # echo `(trap)`         <--- in subshell in subshell - output
5044                  * trap -- 'echo Ho' SIGWINCH
5045                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5046                  * trap -- 'echo Ho' SIGWINCH
5047                  *
5048                  * The rules when to forget and when to not forget traps
5049                  * get really complex and nonsensical.
5050                  *
5051                  * Our solution: ONLY bare $(trap) or `trap` is special.
5052                  */
5053                 /* Save trap handler strings for trap builtin to print */
5054                 trap_ptr = xmemdup(trap, sizeof(trap));
5055                 /* Fall through into clearing traps */
5056         }
5057         clear_traps();
5058 #if JOBS
5059         /* do job control only in root shell */
5060         doing_jobctl = 0;
5061         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5062                 pid_t pgrp;
5063
5064                 if (jp->nprocs == 0)
5065                         pgrp = getpid();
5066                 else
5067                         pgrp = jp->ps[0].ps_pid;
5068                 /* this can fail because we are doing it in the parent also */
5069                 setpgid(0, pgrp);
5070                 if (mode == FORK_FG)
5071                         xtcsetpgrp(ttyfd, pgrp);
5072                 setsignal(SIGTSTP);
5073                 setsignal(SIGTTOU);
5074         } else
5075 #endif
5076         if (mode == FORK_BG) {
5077                 /* man bash: "When job control is not in effect,
5078                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5079                 ignoresig(SIGINT);
5080                 ignoresig(SIGQUIT);
5081                 if (jp->nprocs == 0) {
5082                         close(0);
5083                         if (open(bb_dev_null, O_RDONLY) != 0)
5084                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5085                 }
5086         }
5087         if (oldlvl == 0) {
5088                 if (iflag) { /* why if iflag only? */
5089                         setsignal(SIGINT);
5090                         setsignal(SIGTERM);
5091                 }
5092                 /* man bash:
5093                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5094                  * commands run by bash have signal handlers
5095                  * set to the values inherited by the shell
5096                  * from its parent".
5097                  * Take care of the second rule: */
5098                 setsignal(SIGQUIT);
5099         }
5100 #if JOBS
5101         if (n && n->type == NCMD
5102          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5103         ) {
5104                 TRACE(("Job hack\n"));
5105                 /* "jobs": we do not want to clear job list for it,
5106                  * instead we remove only _its_ own_ job from job list.
5107                  * This makes "jobs .... | cat" more useful.
5108                  */
5109                 freejob(curjob);
5110                 return;
5111         }
5112 #endif
5113         for (jp = curjob; jp; jp = jp->prev_job)
5114                 freejob(jp);
5115         jobless = 0;
5116 }
5117
5118 /* Called after fork(), in parent */
5119 #if !JOBS
5120 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5121 #endif
5122 static void
5123 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5124 {
5125         TRACE(("In parent shell: child = %d\n", pid));
5126         if (!jp) {
5127                 /* jp is NULL when called by openhere() for heredoc support */
5128                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5129                         continue;
5130                 jobless++;
5131                 return;
5132         }
5133 #if JOBS
5134         if (mode != FORK_NOJOB && jp->jobctl) {
5135                 int pgrp;
5136
5137                 if (jp->nprocs == 0)
5138                         pgrp = pid;
5139                 else
5140                         pgrp = jp->ps[0].ps_pid;
5141                 /* This can fail because we are doing it in the child also */
5142                 setpgid(pid, pgrp);
5143         }
5144 #endif
5145         if (mode == FORK_BG) {
5146                 backgndpid = pid;               /* set $! */
5147                 set_curjob(jp, CUR_RUNNING);
5148         }
5149         if (jp) {
5150                 struct procstat *ps = &jp->ps[jp->nprocs++];
5151                 ps->ps_pid = pid;
5152                 ps->ps_status = -1;
5153                 ps->ps_cmd = nullstr;
5154 #if JOBS
5155                 if (doing_jobctl && n)
5156                         ps->ps_cmd = commandtext(n);
5157 #endif
5158         }
5159 }
5160
5161 /* jp and n are NULL when called by openhere() for heredoc support */
5162 static int
5163 forkshell(struct job *jp, union node *n, int mode)
5164 {
5165         int pid;
5166
5167         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5168         pid = fork();
5169         if (pid < 0) {
5170                 TRACE(("Fork failed, errno=%d", errno));
5171                 if (jp)
5172                         freejob(jp);
5173                 ash_msg_and_raise_perror("can't fork");
5174         }
5175         if (pid == 0) {
5176                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5177                 forkchild(jp, n, mode);
5178         } else {
5179                 forkparent(jp, n, mode, pid);
5180         }
5181         return pid;
5182 }
5183
5184 /*
5185  * Wait for job to finish.
5186  *
5187  * Under job control we have the problem that while a child process
5188  * is running interrupts generated by the user are sent to the child
5189  * but not to the shell.  This means that an infinite loop started by
5190  * an interactive user may be hard to kill.  With job control turned off,
5191  * an interactive user may place an interactive program inside a loop.
5192  * If the interactive program catches interrupts, the user doesn't want
5193  * these interrupts to also abort the loop.  The approach we take here
5194  * is to have the shell ignore interrupt signals while waiting for a
5195  * foreground process to terminate, and then send itself an interrupt
5196  * signal if the child process was terminated by an interrupt signal.
5197  * Unfortunately, some programs want to do a bit of cleanup and then
5198  * exit on interrupt; unless these processes terminate themselves by
5199  * sending a signal to themselves (instead of calling exit) they will
5200  * confuse this approach.
5201  *
5202  * Called with interrupts off.
5203  */
5204 static int
5205 waitforjob(struct job *jp)
5206 {
5207         int st;
5208
5209         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5210
5211         INT_OFF;
5212         while (jp->state == JOBRUNNING) {
5213                 /* In non-interactive shells, we _can_ get
5214                  * a keyboard signal here and be EINTRed,
5215                  * but we just loop back, waiting for command to complete.
5216                  *
5217                  * man bash:
5218                  * "If bash is waiting for a command to complete and receives
5219                  * a signal for which a trap has been set, the trap
5220                  * will not be executed until the command completes."
5221                  *
5222                  * Reality is that even if trap is not set, bash
5223                  * will not act on the signal until command completes.
5224                  * Try this. sleep5intoff.c:
5225                  * #include <signal.h>
5226                  * #include <unistd.h>
5227                  * int main() {
5228                  *         sigset_t set;
5229                  *         sigemptyset(&set);
5230                  *         sigaddset(&set, SIGINT);
5231                  *         sigaddset(&set, SIGQUIT);
5232                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5233                  *         sleep(5);
5234                  *         return 0;
5235                  * }
5236                  * $ bash -c './sleep5intoff; echo hi'
5237                  * ^C^C^C^C <--- pressing ^C once a second
5238                  * $ _
5239                  * $ bash -c './sleep5intoff; echo hi'
5240                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5241                  * $ _
5242                  */
5243                 dowait(DOWAIT_BLOCK, jp);
5244         }
5245         INT_ON;
5246
5247         st = getstatus(jp);
5248 #if JOBS
5249         if (jp->jobctl) {
5250                 xtcsetpgrp(ttyfd, rootpid);
5251                 restore_tty_if_stopped_or_signaled(jp);
5252
5253                 /*
5254                  * This is truly gross.
5255                  * If we're doing job control, then we did a TIOCSPGRP which
5256                  * caused us (the shell) to no longer be in the controlling
5257                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5258                  * intuit from the subprocess exit status whether a SIGINT
5259                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5260                  */
5261                 if (jp->sigint) /* TODO: do the same with all signals */
5262                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5263         }
5264         if (jp->state == JOBDONE)
5265 #endif
5266                 freejob(jp);
5267         return st;
5268 }
5269
5270 /*
5271  * return 1 if there are stopped jobs, otherwise 0
5272  */
5273 static int
5274 stoppedjobs(void)
5275 {
5276         struct job *jp;
5277         int retval;
5278
5279         retval = 0;
5280         if (job_warning)
5281                 goto out;
5282         jp = curjob;
5283         if (jp && jp->state == JOBSTOPPED) {
5284                 out2str("You have stopped jobs.\n");
5285                 job_warning = 2;
5286                 retval++;
5287         }
5288  out:
5289         return retval;
5290 }
5291
5292
5293 /*
5294  * Code for dealing with input/output redirection.
5295  */
5296
5297 #undef EMPTY
5298 #undef CLOSED
5299 #define EMPTY -2                /* marks an unused slot in redirtab */
5300 #define CLOSED -1               /* marks a slot of previously-closed fd */
5301
5302 /*
5303  * Handle here documents.  Normally we fork off a process to write the
5304  * data to a pipe.  If the document is short, we can stuff the data in
5305  * the pipe without forking.
5306  */
5307 /* openhere needs this forward reference */
5308 static void expandhere(union node *arg, int fd);
5309 static int
5310 openhere(union node *redir)
5311 {
5312         int pip[2];
5313         size_t len = 0;
5314
5315         if (pipe(pip) < 0)
5316                 ash_msg_and_raise_perror("can't create pipe");
5317         if (redir->type == NHERE) {
5318                 len = strlen(redir->nhere.doc->narg.text);
5319                 if (len <= PIPE_BUF) {
5320                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5321                         goto out;
5322                 }
5323         }
5324         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5325                 /* child */
5326                 close(pip[0]);
5327                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5328                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5329                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5330                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5331                 signal(SIGPIPE, SIG_DFL);
5332                 if (redir->type == NHERE)
5333                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5334                 else /* NXHERE */
5335                         expandhere(redir->nhere.doc, pip[1]);
5336                 _exit(EXIT_SUCCESS);
5337         }
5338  out:
5339         close(pip[1]);
5340         return pip[0];
5341 }
5342
5343 static int
5344 openredirect(union node *redir)
5345 {
5346         struct stat sb;
5347         char *fname;
5348         int f;
5349
5350         switch (redir->nfile.type) {
5351 /* Can't happen, our single caller does this itself */
5352 //      case NTOFD:
5353 //      case NFROMFD:
5354 //              return -1;
5355         case NHERE:
5356         case NXHERE:
5357                 return openhere(redir);
5358         }
5359
5360         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5361          * allocated space. Do it only when we know it is safe.
5362          */
5363         fname = redir->nfile.expfname;
5364
5365         switch (redir->nfile.type) {
5366         default:
5367 #if DEBUG
5368                 abort();
5369 #endif
5370         case NFROM:
5371                 f = open(fname, O_RDONLY);
5372                 if (f < 0)
5373                         goto eopen;
5374                 break;
5375         case NFROMTO:
5376                 f = open(fname, O_RDWR|O_CREAT, 0666);
5377                 if (f < 0)
5378                         goto ecreate;
5379                 break;
5380         case NTO:
5381 #if BASH_REDIR_OUTPUT
5382         case NTO2:
5383 #endif
5384                 /* Take care of noclobber mode. */
5385                 if (Cflag) {
5386                         if (stat(fname, &sb) < 0) {
5387                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5388                                 if (f < 0)
5389                                         goto ecreate;
5390                         } else if (!S_ISREG(sb.st_mode)) {
5391                                 f = open(fname, O_WRONLY, 0666);
5392                                 if (f < 0)
5393                                         goto ecreate;
5394                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5395                                         close(f);
5396                                         errno = EEXIST;
5397                                         goto ecreate;
5398                                 }
5399                         } else {
5400                                 errno = EEXIST;
5401                                 goto ecreate;
5402                         }
5403                         break;
5404                 }
5405                 /* FALLTHROUGH */
5406         case NCLOBBER:
5407                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5408                 if (f < 0)
5409                         goto ecreate;
5410                 break;
5411         case NAPPEND:
5412                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5413                 if (f < 0)
5414                         goto ecreate;
5415                 break;
5416         }
5417
5418         return f;
5419  ecreate:
5420         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5421  eopen:
5422         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5423 }
5424
5425 /*
5426  * Copy a file descriptor to be >= 10. Throws exception on error.
5427  */
5428 static int
5429 savefd(int from)
5430 {
5431         int newfd;
5432         int err;
5433
5434         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5435         err = newfd < 0 ? errno : 0;
5436         if (err != EBADF) {
5437                 if (err)
5438                         ash_msg_and_raise_perror("%d", from);
5439                 close(from);
5440                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5441                         close_on_exec_on(newfd);
5442         }
5443
5444         return newfd;
5445 }
5446 static int
5447 dup2_or_raise(int from, int to)
5448 {
5449         int newfd;
5450
5451         newfd = (from != to) ? dup2(from, to) : to;
5452         if (newfd < 0) {
5453                 /* Happens when source fd is not open: try "echo >&99" */
5454                 ash_msg_and_raise_perror("%d", from);
5455         }
5456         return newfd;
5457 }
5458 static int
5459 dup_CLOEXEC(int fd, int avoid_fd)
5460 {
5461         int newfd;
5462  repeat:
5463         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5464         if (newfd >= 0) {
5465                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5466                         close_on_exec_on(newfd);
5467         } else { /* newfd < 0 */
5468                 if (errno == EBUSY)
5469                         goto repeat;
5470                 if (errno == EINTR)
5471                         goto repeat;
5472         }
5473         return newfd;
5474 }
5475 static int
5476 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5477 {
5478         int newfd;
5479  repeat:
5480         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5481         if (newfd < 0) {
5482                 if (errno == EBUSY)
5483                         goto repeat;
5484                 if (errno == EINTR)
5485                         goto repeat;
5486                 /* fd was not open? */
5487                 if (errno == EBADF)
5488                         return fd;
5489                 ash_msg_and_raise_perror("%d", newfd);
5490         }
5491         if (F_DUPFD_CLOEXEC == F_DUPFD)
5492                 close_on_exec_on(newfd);
5493         close(fd);
5494         return newfd;
5495 }
5496
5497 /* Struct def and variable are moved down to the first usage site */
5498 struct squirrel {
5499         int orig_fd;
5500         int moved_to;
5501 };
5502 struct redirtab {
5503         struct redirtab *next;
5504         int pair_count;
5505         struct squirrel two_fd[];
5506 };
5507 #define redirlist (G_var.redirlist)
5508
5509 static void
5510 add_squirrel_closed(struct redirtab *sq, int fd)
5511 {
5512         int i;
5513
5514         if (!sq)
5515                 return;
5516
5517         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5518                 /* If we collide with an already moved fd... */
5519                 if (fd == sq->two_fd[i].orig_fd) {
5520                         /* Examples:
5521                          * "echo 3>FILE 3>&- 3>FILE"
5522                          * "echo 3>&- 3>FILE"
5523                          * No need for last redirect to insert
5524                          * another "need to close 3" indicator.
5525                          */
5526                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5527                         return;
5528                 }
5529         }
5530         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5531         sq->two_fd[i].orig_fd = fd;
5532         sq->two_fd[i].moved_to = CLOSED;
5533 }
5534
5535 static int
5536 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5537 {
5538         int i, new_fd;
5539
5540         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5541                 avoid_fd = 9;
5542
5543 #if JOBS
5544         if (fd == ttyfd) {
5545                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5546                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5547                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5548                 return 1; /* "we closed fd" */
5549         }
5550 #endif
5551         /* Are we called from redirect(0)? E.g. redirect
5552          * in a forked child. No need to save fds,
5553          * we aren't going to use them anymore, ok to trash.
5554          */
5555         if (!sq)
5556                 return 0;
5557
5558         /* If this one of script's fds? */
5559         if (fd != 0) {
5560                 struct parsefile *pf = g_parsefile;
5561                 while (pf) {
5562                         /* We skip fd == 0 case because of the following:
5563                          * $ ash  # running ash interactively
5564                          * $ . ./script.sh
5565                          * and in script.sh: "exec 9>&0".
5566                          * Even though top-level pf_fd _is_ 0,
5567                          * it's still ok to use it: "read" builtin uses it,
5568                          * why should we cripple "exec" builtin?
5569                          */
5570                         if (fd == pf->pf_fd) {
5571                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5572                                 return 1; /* "we closed fd" */
5573                         }
5574                         pf = pf->prev;
5575                 }
5576         }
5577
5578         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5579
5580         /* First: do we collide with some already moved fds? */
5581         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5582                 /* If we collide with an already moved fd... */
5583                 if (fd == sq->two_fd[i].moved_to) {
5584                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5585                         sq->two_fd[i].moved_to = new_fd;
5586                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5587                         if (new_fd < 0) /* what? */
5588                                 xfunc_die();
5589                         return 0; /* "we did not close fd" */
5590                 }
5591                 if (fd == sq->two_fd[i].orig_fd) {
5592                         /* Example: echo Hello >/dev/null 1>&2 */
5593                         TRACE(("redirect_fd %d: already moved\n", fd));
5594                         return 0; /* "we did not close fd" */
5595                 }
5596         }
5597
5598         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5599         new_fd = dup_CLOEXEC(fd, avoid_fd);
5600         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5601         if (new_fd < 0) {
5602                 if (errno != EBADF)
5603                         xfunc_die();
5604                 /* new_fd = CLOSED; - already is -1 */
5605         }
5606         sq->two_fd[i].moved_to = new_fd;
5607         sq->two_fd[i].orig_fd = fd;
5608
5609         /* if we move stderr, let "set -x" code know */
5610         if (fd == preverrout_fd)
5611                 preverrout_fd = new_fd;
5612
5613         return 0; /* "we did not close fd" */
5614 }
5615
5616 static int
5617 internally_opened_fd(int fd, struct redirtab *sq)
5618 {
5619         int i;
5620 #if JOBS
5621         if (fd == ttyfd)
5622                 return 1;
5623 #endif
5624         /* If this one of script's fds? */
5625         if (fd != 0) {
5626                 struct parsefile *pf = g_parsefile;
5627                 while (pf) {
5628                         if (fd == pf->pf_fd)
5629                                 return 1;
5630                         pf = pf->prev;
5631                 }
5632         }
5633
5634         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5635                 if (fd == sq->two_fd[i].moved_to)
5636                         return 1;
5637         }
5638         return 0;
5639 }
5640
5641 /*
5642  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5643  * old file descriptors are stashed away so that the redirection can be
5644  * undone by calling popredir.
5645  */
5646 /* flags passed to redirect */
5647 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5648 static void
5649 redirect(union node *redir, int flags)
5650 {
5651         struct redirtab *sv;
5652
5653         if (!redir)
5654                 return;
5655
5656         sv = NULL;
5657         INT_OFF;
5658         if (flags & REDIR_PUSH)
5659                 sv = redirlist;
5660         do {
5661                 int fd;
5662                 int newfd;
5663                 int close_fd;
5664                 int closed;
5665
5666                 fd = redir->nfile.fd;
5667                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5668                         //bb_error_msg("doing %d > %d", fd, newfd);
5669                         newfd = redir->ndup.dupfd;
5670                         close_fd = -1;
5671                 } else {
5672                         newfd = openredirect(redir); /* always >= 0 */
5673                         if (fd == newfd) {
5674                                 /* open() gave us precisely the fd we wanted.
5675                                  * This means that this fd was not busy
5676                                  * (not opened to anywhere).
5677                                  * Remember to close it on restore:
5678                                  */
5679                                 add_squirrel_closed(sv, fd);
5680                                 continue;
5681                         }
5682                         close_fd = newfd;
5683                 }
5684
5685                 if (fd == newfd)
5686                         continue;
5687
5688                 /* if "N>FILE": move newfd to fd */
5689                 /* if "N>&M": dup newfd to fd */
5690                 /* if "N>&-": close fd (newfd is -1) */
5691
5692  IF_BASH_REDIR_OUTPUT(redirect_more:)
5693
5694                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5695                 if (newfd == -1) {
5696                         /* "N>&-" means "close me" */
5697                         if (!closed) {
5698                                 /* ^^^ optimization: saving may already
5699                                  * have closed it. If not... */
5700                                 close(fd);
5701                         }
5702                 } else {
5703                         /* if newfd is a script fd or saved fd, simulate EBADF */
5704                         if (internally_opened_fd(newfd, sv)) {
5705                                 errno = EBADF;
5706                                 ash_msg_and_raise_perror("%d", newfd);
5707                         }
5708                         dup2_or_raise(newfd, fd);
5709                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5710                                 close(close_fd);
5711 #if BASH_REDIR_OUTPUT
5712                         if (redir->nfile.type == NTO2 && fd == 1) {
5713                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5714                                 fd = 2;
5715                                 newfd = 1;
5716                                 close_fd = -1;
5717                                 goto redirect_more;
5718                         }
5719 #endif
5720                 }
5721         } while ((redir = redir->nfile.next) != NULL);
5722         INT_ON;
5723
5724 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5725 #define REDIR_SAVEFD2 0
5726         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5727         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5728         // not only for calls with flags containing REDIR_SAVEFD2.
5729         // We do this unconditionally (see save_fd_on_redirect()).
5730         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5731         //      preverrout_fd = copied_fd2;
5732 }
5733
5734 static int
5735 redirectsafe(union node *redir, int flags)
5736 {
5737         int err;
5738         volatile int saveint;
5739         struct jmploc *volatile savehandler = exception_handler;
5740         struct jmploc jmploc;
5741
5742         SAVE_INT(saveint);
5743         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5744         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5745         if (!err) {
5746                 exception_handler = &jmploc;
5747                 redirect(redir, flags);
5748         }
5749         exception_handler = savehandler;
5750         if (err && exception_type != EXERROR)
5751                 longjmp(exception_handler->loc, 1);
5752         RESTORE_INT(saveint);
5753         return err;
5754 }
5755
5756 static struct redirtab*
5757 pushredir(union node *redir)
5758 {
5759         struct redirtab *sv;
5760         int i;
5761
5762         if (!redir)
5763                 return redirlist;
5764
5765         i = 0;
5766         do {
5767                 i++;
5768 #if BASH_REDIR_OUTPUT
5769                 if (redir->nfile.type == NTO2)
5770                         i++;
5771 #endif
5772                 redir = redir->nfile.next;
5773         } while (redir);
5774
5775         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5776         sv->pair_count = i;
5777         while (--i >= 0)
5778                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5779         sv->next = redirlist;
5780         redirlist = sv;
5781         return sv->next;
5782 }
5783
5784 /*
5785  * Undo the effects of the last redirection.
5786  */
5787 static void
5788 popredir(int drop)
5789 {
5790         struct redirtab *rp;
5791         int i;
5792
5793         if (redirlist == NULL)
5794                 return;
5795         INT_OFF;
5796         rp = redirlist;
5797         for (i = 0; i < rp->pair_count; i++) {
5798                 int fd = rp->two_fd[i].orig_fd;
5799                 int copy = rp->two_fd[i].moved_to;
5800                 if (copy == CLOSED) {
5801                         if (!drop)
5802                                 close(fd);
5803                         continue;
5804                 }
5805                 if (copy != EMPTY) {
5806                         if (!drop) {
5807                                 /*close(fd);*/
5808                                 dup2_or_raise(copy, fd);
5809                         }
5810                         close(copy);
5811                 }
5812         }
5813         redirlist = rp->next;
5814         free(rp);
5815         INT_ON;
5816 }
5817
5818 static void
5819 unwindredir(struct redirtab *stop)
5820 {
5821         while (redirlist != stop)
5822                 popredir(/*drop:*/ 0);
5823 }
5824
5825
5826 /* ============ Routines to expand arguments to commands
5827  *
5828  * We have to deal with backquotes, shell variables, and file metacharacters.
5829  */
5830
5831 #if ENABLE_FEATURE_SH_MATH
5832 static arith_t
5833 ash_arith(const char *s)
5834 {
5835         arith_state_t math_state;
5836         arith_t result;
5837
5838         math_state.lookupvar = lookupvar;
5839         math_state.setvar    = setvar0;
5840         //math_state.endofname = endofname;
5841
5842         INT_OFF;
5843         result = arith(&math_state, s);
5844         if (math_state.errmsg)
5845                 ash_msg_and_raise_error(math_state.errmsg);
5846         INT_ON;
5847
5848         return result;
5849 }
5850 #endif
5851 #if BASH_SUBSTR
5852 # if ENABLE_FEATURE_SH_MATH
5853 static int substr_atoi(const char *s)
5854 {
5855         arith_t t = ash_arith(s);
5856         if (sizeof(t) > sizeof(int)) {
5857                 /* clamp very large or very large negative nums for ${v:N:M}:
5858                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5859                  */
5860                 if (t > INT_MAX)
5861                         t = INT_MAX;
5862                 if (t < INT_MIN)
5863                         t = INT_MIN;
5864         }
5865         return t;
5866 }
5867 # else
5868 #  define substr_atoi(s) number(s)
5869 # endif
5870 #endif
5871
5872 /*
5873  * expandarg flags
5874  */
5875 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5876 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5877 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5878 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5879 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5880  * POSIX says for this case:
5881  *  Pathname expansion shall not be performed on the word by a
5882  *  non-interactive shell; an interactive shell may perform it, but shall
5883  *  do so only when the expansion would result in one word.
5884  * Currently, our code complies to the above rule by never globbing
5885  * redirection filenames.
5886  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5887  * (this means that on a typical Linux distro, bash almost always
5888  * performs globbing, and thus diverges from what we do).
5889  */
5890 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5891 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5892 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5893 #define EXP_QUOTED      0x80    /* expand word in double quotes */
5894 /*
5895  * rmescape() flags
5896  */
5897 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5898 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5899 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5900 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5901
5902 /* Add CTLESC when necessary. */
5903 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5904 /* Do not skip NUL characters. */
5905 #define QUOTES_KEEPNUL EXP_TILDE
5906
5907 /*
5908  * Structure specifying which parts of the string should be searched
5909  * for IFS characters.
5910  */
5911 struct ifsregion {
5912         struct ifsregion *next; /* next region in list */
5913         int begoff;             /* offset of start of region */
5914         int endoff;             /* offset of end of region */
5915         int nulonly;            /* search for nul bytes only */
5916 };
5917
5918 struct arglist {
5919         struct strlist *list;
5920         struct strlist **lastp;
5921 };
5922
5923 /* output of current string */
5924 static char *expdest;
5925 /* list of back quote expressions */
5926 static struct nodelist *argbackq;
5927 /* first struct in list of ifs regions */
5928 static struct ifsregion ifsfirst;
5929 /* last struct in list */
5930 static struct ifsregion *ifslastp;
5931 /* holds expanded arg list */
5932 static struct arglist exparg;
5933
5934 /*
5935  * Our own itoa().
5936  * cvtnum() is used even if math support is off (to prepare $? values and such).
5937  */
5938 static int
5939 cvtnum(arith_t num)
5940 {
5941         int len;
5942
5943         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5944         len = sizeof(arith_t) * 3;
5945         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5946         if (sizeof(arith_t) < 4) len += 2;
5947
5948         expdest = makestrspace(len, expdest);
5949         len = fmtstr(expdest, len, ARITH_FMT, num);
5950         STADJUST(len, expdest);
5951         return len;
5952 }
5953
5954 /*
5955  * Break the argument string into pieces based upon IFS and add the
5956  * strings to the argument list.  The regions of the string to be
5957  * searched for IFS characters have been stored by recordregion.
5958  */
5959 static void
5960 ifsbreakup(char *string, struct arglist *arglist)
5961 {
5962         struct ifsregion *ifsp;
5963         struct strlist *sp;
5964         char *start;
5965         char *p;
5966         char *q;
5967         const char *ifs, *realifs;
5968         int ifsspc;
5969         int nulonly;
5970
5971         start = string;
5972         if (ifslastp != NULL) {
5973                 ifsspc = 0;
5974                 nulonly = 0;
5975                 realifs = ifsset() ? ifsval() : defifs;
5976                 ifsp = &ifsfirst;
5977                 do {
5978                         p = string + ifsp->begoff;
5979                         nulonly = ifsp->nulonly;
5980                         ifs = nulonly ? nullstr : realifs;
5981                         ifsspc = 0;
5982                         while (p < string + ifsp->endoff) {
5983                                 q = p;
5984                                 if ((unsigned char)*p == CTLESC)
5985                                         p++;
5986                                 if (!strchr(ifs, *p)) {
5987                                         p++;
5988                                         continue;
5989                                 }
5990                                 if (!nulonly)
5991                                         ifsspc = (strchr(defifs, *p) != NULL);
5992                                 /* Ignore IFS whitespace at start */
5993                                 if (q == start && ifsspc) {
5994                                         p++;
5995                                         start = p;
5996                                         continue;
5997                                 }
5998                                 *q = '\0';
5999                                 sp = stzalloc(sizeof(*sp));
6000                                 sp->text = start;
6001                                 *arglist->lastp = sp;
6002                                 arglist->lastp = &sp->next;
6003                                 p++;
6004                                 if (!nulonly) {
6005                                         for (;;) {
6006                                                 if (p >= string + ifsp->endoff) {
6007                                                         break;
6008                                                 }
6009                                                 q = p;
6010                                                 if ((unsigned char)*p == CTLESC)
6011                                                         p++;
6012                                                 if (strchr(ifs, *p) == NULL) {
6013                                                         p = q;
6014                                                         break;
6015                                                 }
6016                                                 if (strchr(defifs, *p) == NULL) {
6017                                                         if (ifsspc) {
6018                                                                 p++;
6019                                                                 ifsspc = 0;
6020                                                         } else {
6021                                                                 p = q;
6022                                                                 break;
6023                                                         }
6024                                                 } else
6025                                                         p++;
6026                                         }
6027                                 }
6028                                 start = p;
6029                         } /* while */
6030                         ifsp = ifsp->next;
6031                 } while (ifsp != NULL);
6032                 if (nulonly)
6033                         goto add;
6034         }
6035
6036         if (!*start)
6037                 return;
6038
6039  add:
6040         sp = stzalloc(sizeof(*sp));
6041         sp->text = start;
6042         *arglist->lastp = sp;
6043         arglist->lastp = &sp->next;
6044 }
6045
6046 static void
6047 ifsfree(void)
6048 {
6049         struct ifsregion *p = ifsfirst.next;
6050
6051         if (!p)
6052                 goto out;
6053
6054         INT_OFF;
6055         do {
6056                 struct ifsregion *ifsp;
6057                 ifsp = p->next;
6058                 free(p);
6059                 p = ifsp;
6060         } while (p);
6061         ifsfirst.next = NULL;
6062         INT_ON;
6063  out:
6064         ifslastp = NULL;
6065 }
6066
6067 static size_t
6068 esclen(const char *start, const char *p)
6069 {
6070         size_t esc = 0;
6071
6072         while (p > start && (unsigned char)*--p == CTLESC) {
6073                 esc++;
6074         }
6075         return esc;
6076 }
6077
6078 /*
6079  * Remove any CTLESC characters from a string.
6080  */
6081 #if !BASH_PATTERN_SUBST
6082 #define rmescapes(str, flag, slash_position) \
6083         rmescapes(str, flag)
6084 #endif
6085 static char *
6086 rmescapes(char *str, int flag, int *slash_position)
6087 {
6088         static const char qchars[] ALIGN1 = {
6089                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6090
6091         char *p, *q, *r;
6092         unsigned protect_against_glob;
6093         unsigned globbing;
6094
6095         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6096         if (!p)
6097                 return str;
6098
6099         q = p;
6100         r = str;
6101         if (flag & RMESCAPE_ALLOC) {
6102                 size_t len = p - str;
6103                 size_t fulllen = len + strlen(p) + 1;
6104
6105                 if (flag & RMESCAPE_GROW) {
6106                         int strloc = str - (char *)stackblock();
6107                         r = makestrspace(fulllen, expdest);
6108                         /* p and str may be invalidated by makestrspace */
6109                         str = (char *)stackblock() + strloc;
6110                         p = str + len;
6111                 } else if (flag & RMESCAPE_HEAP) {
6112                         r = ckmalloc(fulllen);
6113                 } else {
6114                         r = stalloc(fulllen);
6115                 }
6116                 q = r;
6117                 if (len > 0) {
6118                         q = (char *)mempcpy(q, str, len);
6119                 }
6120         }
6121
6122         globbing = flag & RMESCAPE_GLOB;
6123         protect_against_glob = globbing;
6124         while (*p) {
6125                 if ((unsigned char)*p == CTLQUOTEMARK) {
6126 // Note: protect_against_glob only affect whether
6127 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6128                         p++;
6129                         protect_against_glob = globbing;
6130                         continue;
6131                 }
6132                 if (*p == '\\') {
6133                         /* naked back slash */
6134                         protect_against_glob = 0;
6135                         goto copy;
6136                 }
6137                 if ((unsigned char)*p == CTLESC) {
6138                         p++;
6139 #if DEBUG
6140                         if (*p == '\0')
6141                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6142 #endif
6143                         if (protect_against_glob) {
6144                                 /*
6145                                  * We used to trust glob() and fnmatch() to eat
6146                                  * superfluous escapes (\z where z has no
6147                                  * special meaning anyway). But this causes
6148                                  * bugs such as string of one greek letter rho
6149                                  * (unicode-encoded as two bytes "cf,81")
6150                                  * getting encoded as "cf,CTLESC,81"
6151                                  * and here, converted to "cf,\,81" -
6152                                  * which does not go well with some flavors
6153                                  * of fnmatch() in unicode locales
6154                                  * (for example, glibc <= 2.22).
6155                                  *
6156                                  * Lets add "\" only on the chars which need it.
6157                                  * Testcases for less obvious chars are shown.
6158                                  */
6159                                 if (*p == '*'
6160                                  || *p == '?'
6161                                  || *p == '['
6162                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6163                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6164                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6165                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6166                                 /* Some libc support [^negate], that's why "^" also needs love */
6167                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6168                                 ) {
6169                                         *q++ = '\\';
6170                                 }
6171                         }
6172                 }
6173 #if BASH_PATTERN_SUBST
6174                 else if (slash_position && p == str + *slash_position) {
6175                         /* stop handling globbing */
6176                         globbing = 0;
6177                         *slash_position = q - r;
6178                         slash_position = NULL;
6179                 }
6180 #endif
6181                 protect_against_glob = globbing;
6182  copy:
6183                 *q++ = *p++;
6184         }
6185         *q = '\0';
6186         if (flag & RMESCAPE_GROW) {
6187                 expdest = r;
6188                 STADJUST(q - r + 1, expdest);
6189         }
6190         return r;
6191 }
6192 #define pmatch(a, b) !fnmatch((a), (b), 0)
6193
6194 /*
6195  * Prepare a pattern for a expmeta (internal glob(3)) call.
6196  *
6197  * Returns an stalloced string.
6198  */
6199 static char *
6200 preglob(const char *pattern, int flag)
6201 {
6202         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6203 }
6204
6205 /*
6206  * Put a string on the stack.
6207  */
6208 static void
6209 memtodest(const char *p, size_t len, int syntax, int quotes)
6210 {
6211         char *q;
6212
6213         if (!len)
6214                 return;
6215
6216         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6217
6218         do {
6219                 unsigned char c = *p++;
6220                 if (c) {
6221                         if (quotes & QUOTES_ESC) {
6222                                 int n = SIT(c, syntax);
6223                                 if (n == CCTL
6224                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6225                                      && n == CBACK
6226                                     )
6227                                 ) {
6228                                         USTPUTC(CTLESC, q);
6229                                 }
6230                         }
6231                 } else if (!(quotes & QUOTES_KEEPNUL))
6232                         continue;
6233                 USTPUTC(c, q);
6234         } while (--len);
6235
6236         expdest = q;
6237 }
6238
6239 static size_t
6240 strtodest(const char *p, int syntax, int quotes)
6241 {
6242         size_t len = strlen(p);
6243         memtodest(p, len, syntax, quotes);
6244         return len;
6245 }
6246
6247 /*
6248  * Record the fact that we have to scan this region of the
6249  * string for IFS characters.
6250  */
6251 static void
6252 recordregion(int start, int end, int nulonly)
6253 {
6254         struct ifsregion *ifsp;
6255
6256         if (ifslastp == NULL) {
6257                 ifsp = &ifsfirst;
6258         } else {
6259                 INT_OFF;
6260                 ifsp = ckzalloc(sizeof(*ifsp));
6261                 /*ifsp->next = NULL; - ckzalloc did it */
6262                 ifslastp->next = ifsp;
6263                 INT_ON;
6264         }
6265         ifslastp = ifsp;
6266         ifslastp->begoff = start;
6267         ifslastp->endoff = end;
6268         ifslastp->nulonly = nulonly;
6269 }
6270
6271 static void
6272 removerecordregions(int endoff)
6273 {
6274         if (ifslastp == NULL)
6275                 return;
6276
6277         if (ifsfirst.endoff > endoff) {
6278                 while (ifsfirst.next) {
6279                         struct ifsregion *ifsp;
6280                         INT_OFF;
6281                         ifsp = ifsfirst.next->next;
6282                         free(ifsfirst.next);
6283                         ifsfirst.next = ifsp;
6284                         INT_ON;
6285                 }
6286                 if (ifsfirst.begoff > endoff) {
6287                         ifslastp = NULL;
6288                 } else {
6289                         ifslastp = &ifsfirst;
6290                         ifsfirst.endoff = endoff;
6291                 }
6292                 return;
6293         }
6294
6295         ifslastp = &ifsfirst;
6296         while (ifslastp->next && ifslastp->next->begoff < endoff)
6297                 ifslastp = ifslastp->next;
6298         while (ifslastp->next) {
6299                 struct ifsregion *ifsp;
6300                 INT_OFF;
6301                 ifsp = ifslastp->next->next;
6302                 free(ifslastp->next);
6303                 ifslastp->next = ifsp;
6304                 INT_ON;
6305         }
6306         if (ifslastp->endoff > endoff)
6307                 ifslastp->endoff = endoff;
6308 }
6309
6310 static char *
6311 exptilde(char *startp, char *p, int flags)
6312 {
6313         unsigned char c;
6314         char *name;
6315         struct passwd *pw;
6316         const char *home;
6317         int quotes = flags & QUOTES_ESC;
6318
6319         name = p + 1;
6320
6321         while ((c = *++p) != '\0') {
6322                 switch (c) {
6323                 case CTLESC:
6324                         return startp;
6325                 case CTLQUOTEMARK:
6326                         return startp;
6327                 case ':':
6328                         if (flags & EXP_VARTILDE)
6329                                 goto done;
6330                         break;
6331                 case '/':
6332                 case CTLENDVAR:
6333                         goto done;
6334                 }
6335         }
6336  done:
6337         *p = '\0';
6338         if (*name == '\0') {
6339                 home = lookupvar("HOME");
6340         } else {
6341                 pw = getpwnam(name);
6342                 if (pw == NULL)
6343                         goto lose;
6344                 home = pw->pw_dir;
6345         }
6346         if (!home || !*home)
6347                 goto lose;
6348         *p = c;
6349         strtodest(home, SQSYNTAX, quotes);
6350         return p;
6351  lose:
6352         *p = c;
6353         return startp;
6354 }
6355
6356 /*
6357  * Execute a command inside back quotes.  If it's a builtin command, we
6358  * want to save its output in a block obtained from malloc.  Otherwise
6359  * we fork off a subprocess and get the output of the command via a pipe.
6360  * Should be called with interrupts off.
6361  */
6362 struct backcmd {                /* result of evalbackcmd */
6363         int fd;                 /* file descriptor to read from */
6364         int nleft;              /* number of chars in buffer */
6365         char *buf;              /* buffer */
6366         struct job *jp;         /* job structure for command */
6367 };
6368
6369 /* These forward decls are needed to use "eval" code for backticks handling: */
6370 /* flags in argument to evaltree */
6371 #define EV_EXIT    01           /* exit after evaluating tree */
6372 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6373 static int evaltree(union node *, int);
6374
6375 /* An evaltree() which is known to never return.
6376  * Used to use an alias:
6377  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6378  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6379  */
6380 static ALWAYS_INLINE NORETURN void
6381 evaltreenr(union node *n, int flags)
6382 {
6383         evaltree(n, flags);
6384         bb_unreachable(abort());
6385         /* NOTREACHED */
6386 }
6387
6388 static void FAST_FUNC
6389 evalbackcmd(union node *n, struct backcmd *result)
6390 {
6391         int pip[2];
6392         struct job *jp;
6393
6394         result->fd = -1;
6395         result->buf = NULL;
6396         result->nleft = 0;
6397         result->jp = NULL;
6398         if (n == NULL) {
6399                 goto out;
6400         }
6401
6402         if (pipe(pip) < 0)
6403                 ash_msg_and_raise_perror("can't create pipe");
6404         jp = makejob(/*n,*/ 1);
6405         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6406                 /* child */
6407                 FORCE_INT_ON;
6408                 close(pip[0]);
6409                 if (pip[1] != 1) {
6410                         /*close(1);*/
6411                         dup2_or_raise(pip[1], 1);
6412                         close(pip[1]);
6413                 }
6414 /* TODO: eflag clearing makes the following not abort:
6415  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6416  * which is what bash does (unless it is in POSIX mode).
6417  * dash deleted "eflag = 0" line in the commit
6418  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6419  *  [EVAL] Don't clear eflag in evalbackcmd
6420  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6421  */
6422                 eflag = 0;
6423                 ifsfree();
6424                 evaltreenr(n, EV_EXIT);
6425                 /* NOTREACHED */
6426         }
6427         /* parent */
6428         close(pip[1]);
6429         result->fd = pip[0];
6430         result->jp = jp;
6431
6432  out:
6433         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6434                 result->fd, result->buf, result->nleft, result->jp));
6435 }
6436
6437 /*
6438  * Expand stuff in backwards quotes.
6439  */
6440 static void
6441 expbackq(union node *cmd, int flag)
6442 {
6443         struct backcmd in;
6444         int i;
6445         char buf[128];
6446         char *p;
6447         char *dest;
6448         int startloc;
6449         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6450         struct stackmark smark;
6451
6452         INT_OFF;
6453         startloc = expdest - (char *)stackblock();
6454         pushstackmark(&smark, startloc);
6455         evalbackcmd(cmd, &in);
6456         popstackmark(&smark);
6457
6458         p = in.buf;
6459         i = in.nleft;
6460         if (i == 0)
6461                 goto read;
6462         for (;;) {
6463                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6464  read:
6465                 if (in.fd < 0)
6466                         break;
6467                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6468                 TRACE(("expbackq: read returns %d\n", i));
6469                 if (i <= 0)
6470                         break;
6471                 p = buf;
6472         }
6473
6474         free(in.buf);
6475         if (in.fd >= 0) {
6476                 close(in.fd);
6477                 back_exitstatus = waitforjob(in.jp);
6478         }
6479         INT_ON;
6480
6481         /* Eat all trailing newlines */
6482         dest = expdest;
6483         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6484                 STUNPUTC(dest);
6485         expdest = dest;
6486
6487         if (!(flag & EXP_QUOTED))
6488                 recordregion(startloc, dest - (char *)stackblock(), 0);
6489         TRACE(("evalbackq: size:%d:'%.*s'\n",
6490                 (int)((dest - (char *)stackblock()) - startloc),
6491                 (int)((dest - (char *)stackblock()) - startloc),
6492                 stackblock() + startloc));
6493 }
6494
6495 #if ENABLE_FEATURE_SH_MATH
6496 /*
6497  * Expand arithmetic expression.  Backup to start of expression,
6498  * evaluate, place result in (backed up) result, adjust string position.
6499  */
6500 static void
6501 expari(int flag)
6502 {
6503         char *p, *start;
6504         int begoff;
6505         int len;
6506
6507         /* ifsfree(); */
6508
6509         /*
6510          * This routine is slightly over-complicated for
6511          * efficiency.  Next we scan backwards looking for the
6512          * start of arithmetic.
6513          */
6514         start = stackblock();
6515         p = expdest - 1;
6516         *p = '\0';
6517         p--;
6518         while (1) {
6519                 int esc;
6520
6521                 while ((unsigned char)*p != CTLARI) {
6522                         p--;
6523 #if DEBUG
6524                         if (p < start) {
6525                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6526                         }
6527 #endif
6528                 }
6529
6530                 esc = esclen(start, p);
6531                 if (!(esc % 2)) {
6532                         break;
6533                 }
6534
6535                 p -= esc + 1;
6536         }
6537
6538         begoff = p - start;
6539
6540         removerecordregions(begoff);
6541
6542         expdest = p;
6543
6544         if (flag & QUOTES_ESC)
6545                 rmescapes(p + 1, 0, NULL);
6546
6547         len = cvtnum(ash_arith(p + 1));
6548
6549         if (!(flag & EXP_QUOTED))
6550                 recordregion(begoff, begoff + len, 0);
6551 }
6552 #endif
6553
6554 /* argstr needs it */
6555 static char *evalvar(char *p, int flags);
6556
6557 /*
6558  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6559  * characters to allow for further processing.  Otherwise treat
6560  * $@ like $* since no splitting will be performed.
6561  */
6562 static void
6563 argstr(char *p, int flags)
6564 {
6565         static const char spclchars[] ALIGN1 = {
6566                 '=',
6567                 ':',
6568                 CTLQUOTEMARK,
6569                 CTLENDVAR,
6570                 CTLESC,
6571                 CTLVAR,
6572                 CTLBACKQ,
6573 #if ENABLE_FEATURE_SH_MATH
6574                 CTLENDARI,
6575 #endif
6576                 '\0'
6577         };
6578         const char *reject = spclchars;
6579         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6580         int inquotes;
6581         size_t length;
6582         int startloc;
6583
6584         if (!(flags & EXP_VARTILDE)) {
6585                 reject += 2;
6586         } else if (flags & EXP_VARTILDE2) {
6587                 reject++;
6588         }
6589         inquotes = 0;
6590         length = 0;
6591         if (flags & EXP_TILDE) {
6592                 char *q;
6593
6594                 flags &= ~EXP_TILDE;
6595  tilde:
6596                 q = p;
6597                 if (*q == '~')
6598                         p = exptilde(p, q, flags);
6599         }
6600  start:
6601         startloc = expdest - (char *)stackblock();
6602         for (;;) {
6603                 unsigned char c;
6604
6605                 length += strcspn(p + length, reject);
6606                 c = p[length];
6607                 if (c) {
6608                         if (!(c & 0x80)
6609                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6610                         ) {
6611                                 /* c == '=' || c == ':' || c == CTLENDARI */
6612                                 length++;
6613                         }
6614                 }
6615                 if (length > 0) {
6616                         int newloc;
6617                         expdest = stack_nputstr(p, length, expdest);
6618                         newloc = expdest - (char *)stackblock();
6619                         if (breakall && !inquotes && newloc > startloc) {
6620                                 recordregion(startloc, newloc, 0);
6621                         }
6622                         startloc = newloc;
6623                 }
6624                 p += length + 1;
6625                 length = 0;
6626
6627                 switch (c) {
6628                 case '\0':
6629                         goto breakloop;
6630                 case '=':
6631                         if (flags & EXP_VARTILDE2) {
6632                                 p--;
6633                                 continue;
6634                         }
6635                         flags |= EXP_VARTILDE2;
6636                         reject++;
6637                         /* fall through */
6638                 case ':':
6639                         /*
6640                          * sort of a hack - expand tildes in variable
6641                          * assignments (after the first '=' and after ':'s).
6642                          */
6643                         if (*--p == '~') {
6644                                 goto tilde;
6645                         }
6646                         continue;
6647                 }
6648
6649                 switch (c) {
6650                 case CTLENDVAR: /* ??? */
6651                         goto breakloop;
6652                 case CTLQUOTEMARK:
6653                         inquotes ^= EXP_QUOTED;
6654                         /* "$@" syntax adherence hack */
6655                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6656                                 p = evalvar(p + 1, flags | inquotes) + 1;
6657                                 goto start;
6658                         }
6659  addquote:
6660                         if (flags & QUOTES_ESC) {
6661                                 p--;
6662                                 length++;
6663                                 startloc++;
6664                         }
6665                         break;
6666                 case CTLESC:
6667                         startloc++;
6668                         length++;
6669                         goto addquote;
6670                 case CTLVAR:
6671                         TRACE(("argstr: evalvar('%s')\n", p));
6672                         p = evalvar(p, flags | inquotes);
6673                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6674                         goto start;
6675                 case CTLBACKQ:
6676                         expbackq(argbackq->n, flags | inquotes);
6677                         argbackq = argbackq->next;
6678                         goto start;
6679 #if ENABLE_FEATURE_SH_MATH
6680                 case CTLENDARI:
6681                         p--;
6682                         expari(flags | inquotes);
6683                         goto start;
6684 #endif
6685                 }
6686         }
6687  breakloop: ;
6688 }
6689
6690 static char *
6691 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6692                 char *pattern, int quotes, int zero)
6693 {
6694         char *loc, *loc2;
6695         char c;
6696
6697         loc = startp;
6698         loc2 = rmesc;
6699         do {
6700                 int match;
6701                 const char *s = loc2;
6702
6703                 c = *loc2;
6704                 if (zero) {
6705                         *loc2 = '\0';
6706                         s = rmesc;
6707                 }
6708                 match = pmatch(pattern, s);
6709
6710                 *loc2 = c;
6711                 if (match)
6712                         return loc;
6713                 if (quotes && (unsigned char)*loc == CTLESC)
6714                         loc++;
6715                 loc++;
6716                 loc2++;
6717         } while (c);
6718         return NULL;
6719 }
6720
6721 static char *
6722 scanright(char *startp, char *rmesc, char *rmescend,
6723                 char *pattern, int quotes, int match_at_start)
6724 {
6725 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6726         int try2optimize = match_at_start;
6727 #endif
6728         int esc = 0;
6729         char *loc;
6730         char *loc2;
6731
6732         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6733          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6734          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6735          * Logic:
6736          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6737          * and on each iteration they go back two/one char until they reach the beginning.
6738          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6739          */
6740         /* TODO: document in what other circumstances we are called. */
6741
6742         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6743                 int match;
6744                 char c = *loc2;
6745                 const char *s = loc2;
6746                 if (match_at_start) {
6747                         *loc2 = '\0';
6748                         s = rmesc;
6749                 }
6750                 match = pmatch(pattern, s);
6751                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6752                 *loc2 = c;
6753                 if (match)
6754                         return loc;
6755 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6756                 if (try2optimize) {
6757                         /* Maybe we can optimize this:
6758                          * if pattern ends with unescaped *, we can avoid checking
6759                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6760                          * it won't match truncated "raw_value_of_" strings too.
6761                          */
6762                         unsigned plen = strlen(pattern);
6763                         /* Does it end with "*"? */
6764                         if (plen != 0 && pattern[--plen] == '*') {
6765                                 /* "xxxx*" is not escaped */
6766                                 /* "xxx\*" is escaped */
6767                                 /* "xx\\*" is not escaped */
6768                                 /* "x\\\*" is escaped */
6769                                 int slashes = 0;
6770                                 while (plen != 0 && pattern[--plen] == '\\')
6771                                         slashes++;
6772                                 if (!(slashes & 1))
6773                                         break; /* ends with unescaped "*" */
6774                         }
6775                         try2optimize = 0;
6776                 }
6777 #endif
6778                 loc--;
6779                 if (quotes) {
6780                         if (--esc < 0) {
6781                                 esc = esclen(startp, loc);
6782                         }
6783                         if (esc % 2) {
6784                                 esc--;
6785                                 loc--;
6786                         }
6787                 }
6788         }
6789         return NULL;
6790 }
6791
6792 static void varunset(const char *, const char *, const char *, int) NORETURN;
6793 static void
6794 varunset(const char *end, const char *var, const char *umsg, int varflags)
6795 {
6796         const char *msg;
6797         const char *tail;
6798
6799         tail = nullstr;
6800         msg = "parameter not set";
6801         if (umsg) {
6802                 if ((unsigned char)*end == CTLENDVAR) {
6803                         if (varflags & VSNUL)
6804                                 tail = " or null";
6805                 } else {
6806                         msg = umsg;
6807                 }
6808         }
6809         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6810 }
6811
6812 static const char *
6813 subevalvar(char *p, char *varname, int strloc, int subtype,
6814                 int startloc, int varflags, int flag)
6815 {
6816         struct nodelist *saveargbackq = argbackq;
6817         int quotes = flag & QUOTES_ESC;
6818         char *startp;
6819         char *loc;
6820         char *rmesc, *rmescend;
6821         char *str;
6822         int amount, resetloc;
6823         int argstr_flags;
6824         IF_BASH_PATTERN_SUBST(int workloc;)
6825         IF_BASH_PATTERN_SUBST(int slash_pos;)
6826         IF_BASH_PATTERN_SUBST(char *repl;)
6827         int zero;
6828         char *(*scan)(char*, char*, char*, char*, int, int);
6829
6830         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6831         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6832
6833 #if BASH_PATTERN_SUBST
6834         /* For "${v/pattern/repl}", we must find the delimiter _before_
6835          * argstr() call expands possible variable references in pattern:
6836          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6837          */
6838         repl = NULL;
6839         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6840                 /* Find '/' and replace with NUL */
6841                 repl = p;
6842                 for (;;) {
6843                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6844                         if (*repl == '\0') {
6845                                 repl = NULL;
6846                                 break;
6847                         }
6848                         if (*repl == '/') {
6849                                 *repl = '\0';
6850                                 break;
6851                         }
6852                         if ((unsigned char)*repl == CTLESC && repl[1])
6853                                 repl++;
6854                         repl++;
6855                 }
6856         }
6857 #endif
6858         argstr_flags = EXP_TILDE;
6859         if (subtype != VSASSIGN
6860          && subtype != VSQUESTION
6861 #if BASH_SUBSTR
6862          && subtype != VSSUBSTR
6863 #endif
6864         ) {
6865                 /* EXP_CASE keeps CTLESC's */
6866                 argstr_flags = EXP_TILDE | EXP_CASE;
6867         }
6868         argstr(p, argstr_flags);
6869         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6870 #if BASH_PATTERN_SUBST
6871         slash_pos = -1;
6872         if (repl) {
6873                 slash_pos = expdest - ((char *)stackblock() + strloc);
6874                 STPUTC('/', expdest);
6875                 //bb_error_msg("repl+1:'%s'", repl + 1);
6876                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6877                 *repl = '/';
6878         }
6879 #endif
6880         STPUTC('\0', expdest);
6881         argbackq = saveargbackq;
6882         startp = (char *)stackblock() + startloc;
6883         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6884
6885         switch (subtype) {
6886         case VSASSIGN:
6887                 setvar0(varname, startp);
6888                 amount = startp - expdest;
6889                 STADJUST(amount, expdest);
6890                 return startp;
6891
6892         case VSQUESTION:
6893                 varunset(p, varname, startp, varflags);
6894                 /* NOTREACHED */
6895
6896 #if BASH_SUBSTR
6897         case VSSUBSTR: {
6898                 int pos, len, orig_len;
6899                 char *colon;
6900
6901                 loc = str = stackblock() + strloc;
6902
6903                 /* Read POS in ${var:POS:LEN} */
6904                 colon = strchr(loc, ':');
6905                 if (colon) *colon = '\0';
6906                 pos = substr_atoi(loc);
6907                 if (colon) *colon = ':';
6908
6909                 /* Read LEN in ${var:POS:LEN} */
6910                 len = str - startp - 1;
6911                 /* *loc != '\0', guaranteed by parser */
6912                 if (quotes) {
6913                         char *ptr;
6914                         /* Adjust the length by the number of escapes */
6915                         for (ptr = startp; ptr < (str - 1); ptr++) {
6916                                 if ((unsigned char)*ptr == CTLESC) {
6917                                         len--;
6918                                         ptr++;
6919                                 }
6920                         }
6921                 }
6922                 orig_len = len;
6923                 if (*loc++ == ':') {
6924                         /* ${var::LEN} */
6925                         len = substr_atoi(loc);
6926                 } else {
6927                         /* Skip POS in ${var:POS:LEN} */
6928                         len = orig_len;
6929                         while (*loc && *loc != ':')
6930                                 loc++;
6931                         if (*loc++ == ':')
6932                                 len = substr_atoi(loc);
6933                 }
6934                 if (pos < 0) {
6935                         /* ${VAR:$((-n)):l} starts n chars from the end */
6936                         pos = orig_len + pos;
6937                 }
6938                 if ((unsigned)pos >= orig_len) {
6939                         /* apart from obvious ${VAR:999999:l},
6940                          * covers ${VAR:$((-9999999)):l} - result is ""
6941                          * (bash compat)
6942                          */
6943                         pos = 0;
6944                         len = 0;
6945                 }
6946                 if (len < 0) {
6947                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6948                         len = (orig_len - pos) + len;
6949                 }
6950                 if ((unsigned)len > (orig_len - pos))
6951                         len = orig_len - pos;
6952
6953                 for (str = startp; pos; str++, pos--) {
6954                         if (quotes && (unsigned char)*str == CTLESC)
6955                                 str++;
6956                 }
6957                 for (loc = startp; len; len--) {
6958                         if (quotes && (unsigned char)*str == CTLESC)
6959                                 *loc++ = *str++;
6960                         *loc++ = *str++;
6961                 }
6962                 *loc = '\0';
6963                 amount = loc - expdest;
6964                 STADJUST(amount, expdest);
6965                 return loc;
6966         }
6967 #endif /* BASH_SUBSTR */
6968         }
6969
6970         resetloc = expdest - (char *)stackblock();
6971
6972 #if BASH_PATTERN_SUBST
6973         repl = NULL;
6974
6975         /* We'll comeback here if we grow the stack while handling
6976          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6977          * stack will need rebasing, and we'll need to remove our work
6978          * areas each time
6979          */
6980  restart:
6981 #endif
6982
6983         amount = expdest - ((char *)stackblock() + resetloc);
6984         STADJUST(-amount, expdest);
6985         startp = (char *)stackblock() + startloc;
6986
6987         rmesc = startp;
6988         rmescend = (char *)stackblock() + strloc;
6989         //bb_error_msg("str7:'%s'", rmescend);
6990         if (quotes) {
6991 //TODO: how to handle slash_pos here if string changes (shortens?)
6992                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6993                 if (rmesc != startp) {
6994                         rmescend = expdest;
6995                         startp = (char *)stackblock() + startloc;
6996                 }
6997         }
6998         rmescend--;
6999         str = (char *)stackblock() + strloc;
7000         /*
7001          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7002          * The result is a_\_z_c (not a\_\_z_c)!
7003          *
7004          * The search pattern and replace string treat backslashes differently!
7005          * "&slash_pos" causes rmescapes() to work differently on the pattern
7006          * and string.  It's only used on the first call.
7007          */
7008         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7009         rmescapes(str, RMESCAPE_GLOB,
7010                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7011         );
7012
7013 #if BASH_PATTERN_SUBST
7014         workloc = expdest - (char *)stackblock();
7015         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7016                 int len;
7017                 char *idx, *end;
7018
7019                 if (!repl) {
7020                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7021                         repl = nullstr;
7022                         if (slash_pos >= 0) {
7023                                 repl = str + slash_pos;
7024                                 *repl++ = '\0';
7025                         }
7026                 }
7027                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7028
7029                 /* If there's no pattern to match, return the expansion unmolested */
7030                 if (str[0] == '\0')
7031                         return NULL;
7032
7033                 len = 0;
7034                 idx = startp;
7035                 end = str - 1;
7036                 while (idx < end) {
7037  try_to_match:
7038                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7039                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7040                         if (!loc) {
7041                                 /* No match, advance */
7042                                 char *restart_detect = stackblock();
7043  skip_matching:
7044                                 STPUTC(*idx, expdest);
7045                                 if (quotes && (unsigned char)*idx == CTLESC) {
7046                                         idx++;
7047                                         len++;
7048                                         STPUTC(*idx, expdest);
7049                                 }
7050                                 if (stackblock() != restart_detect)
7051                                         goto restart;
7052                                 idx++;
7053                                 len++;
7054                                 rmesc++;
7055                                 /* continue; - prone to quadratic behavior, smarter code: */
7056                                 if (idx >= end)
7057                                         break;
7058                                 if (str[0] == '*') {
7059                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7060                                          * it would never match "ong_string" etc, no point in trying.
7061                                          */
7062                                         goto skip_matching;
7063                                 }
7064                                 goto try_to_match;
7065                         }
7066
7067                         if (subtype == VSREPLACEALL) {
7068                                 while (idx < loc) {
7069                                         if (quotes && (unsigned char)*idx == CTLESC)
7070                                                 idx++;
7071                                         idx++;
7072                                         rmesc++;
7073                                 }
7074                         } else {
7075                                 idx = loc;
7076                         }
7077
7078                         //bb_error_msg("repl:'%s'", repl);
7079                         for (loc = (char*)repl; *loc; loc++) {
7080                                 char *restart_detect = stackblock();
7081                                 if (quotes && *loc == '\\') {
7082                                         STPUTC(CTLESC, expdest);
7083                                         len++;
7084                                 }
7085                                 STPUTC(*loc, expdest);
7086                                 if (stackblock() != restart_detect)
7087                                         goto restart;
7088                                 len++;
7089                         }
7090
7091                         if (subtype == VSREPLACE) {
7092                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7093                                 while (*idx) {
7094                                         char *restart_detect = stackblock();
7095                                         STPUTC(*idx, expdest);
7096                                         if (stackblock() != restart_detect)
7097                                                 goto restart;
7098                                         len++;
7099                                         idx++;
7100                                 }
7101                                 break;
7102                         }
7103                 }
7104
7105                 /* We've put the replaced text into a buffer at workloc, now
7106                  * move it to the right place and adjust the stack.
7107                  */
7108                 STPUTC('\0', expdest);
7109                 startp = (char *)stackblock() + startloc;
7110                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7111                 //bb_error_msg("startp:'%s'", startp);
7112                 amount = expdest - (startp + len);
7113                 STADJUST(-amount, expdest);
7114                 return startp;
7115         }
7116 #endif /* BASH_PATTERN_SUBST */
7117
7118         subtype -= VSTRIMRIGHT;
7119 #if DEBUG
7120         if (subtype < 0 || subtype > 7)
7121                 abort();
7122 #endif
7123         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7124         zero = subtype >> 1;
7125         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7126         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7127
7128         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7129         if (loc) {
7130                 if (zero) {
7131                         memmove(startp, loc, str - loc);
7132                         loc = startp + (str - loc) - 1;
7133                 }
7134                 *loc = '\0';
7135                 amount = loc - expdest;
7136                 STADJUST(amount, expdest);
7137         }
7138         return loc;
7139 }
7140
7141 /*
7142  * Add the value of a specialized variable to the stack string.
7143  * name parameter (examples):
7144  * ash -c 'echo $1'      name:'1='
7145  * ash -c 'echo $qwe'    name:'qwe='
7146  * ash -c 'echo $$'      name:'$='
7147  * ash -c 'echo ${$}'    name:'$='
7148  * ash -c 'echo ${$##q}' name:'$=q'
7149  * ash -c 'echo ${#$}'   name:'$='
7150  * note: examples with bad shell syntax:
7151  * ash -c 'echo ${#$1}'  name:'$=1'
7152  * ash -c 'echo ${#1#}'  name:'1=#'
7153  */
7154 static NOINLINE ssize_t
7155 varvalue(char *name, int varflags, int flags, int *quotedp)
7156 {
7157         const char *p;
7158         int num;
7159         int i;
7160         ssize_t len = 0;
7161         int sep;
7162         int quoted = *quotedp;
7163         int subtype = varflags & VSTYPE;
7164         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7165         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7166         int syntax;
7167
7168         sep = (flags & EXP_FULL) << CHAR_BIT;
7169         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7170
7171         switch (*name) {
7172         case '$':
7173                 num = rootpid;
7174                 goto numvar;
7175         case '?':
7176                 num = exitstatus;
7177                 goto numvar;
7178         case '#':
7179                 num = shellparam.nparam;
7180                 goto numvar;
7181         case '!':
7182                 num = backgndpid;
7183                 if (num == 0)
7184                         return -1;
7185  numvar:
7186                 len = cvtnum(num);
7187                 goto check_1char_name;
7188         case '-':
7189                 expdest = makestrspace(NOPTS, expdest);
7190                 for (i = NOPTS - 1; i >= 0; i--) {
7191                         if (optlist[i] && optletters(i)) {
7192                                 USTPUTC(optletters(i), expdest);
7193                                 len++;
7194                         }
7195                 }
7196  check_1char_name:
7197 #if 0
7198                 /* handles cases similar to ${#$1} */
7199                 if (name[2] != '\0')
7200                         raise_error_syntax("bad substitution");
7201 #endif
7202                 break;
7203         case '@':
7204                 if (quoted && sep)
7205                         goto param;
7206                 /* fall through */
7207         case '*': {
7208                 char **ap;
7209                 char sepc;
7210
7211                 if (quoted)
7212                         sep = 0;
7213                 sep |= ifsset() ? ifsval()[0] : ' ';
7214  param:
7215                 sepc = sep;
7216                 *quotedp = !sepc;
7217                 ap = shellparam.p;
7218                 if (!ap)
7219                         return -1;
7220                 while ((p = *ap++) != NULL) {
7221                         len += strtodest(p, syntax, quotes);
7222
7223                         if (*ap && sep) {
7224                                 len++;
7225                                 memtodest(&sepc, 1, syntax, quotes);
7226                         }
7227                 }
7228                 break;
7229         } /* case '*' */
7230         case '0':
7231         case '1':
7232         case '2':
7233         case '3':
7234         case '4':
7235         case '5':
7236         case '6':
7237         case '7':
7238         case '8':
7239         case '9':
7240                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7241                 if (num < 0 || num > shellparam.nparam)
7242                         return -1;
7243                 p = num ? shellparam.p[num - 1] : arg0;
7244                 goto value;
7245         default:
7246                 /* NB: name has form "VAR=..." */
7247                 p = lookupvar(name);
7248  value:
7249                 if (!p)
7250                         return -1;
7251
7252                 len = strtodest(p, syntax, quotes);
7253 #if ENABLE_UNICODE_SUPPORT
7254                 if (subtype == VSLENGTH && len > 0) {
7255                         reinit_unicode_for_ash();
7256                         if (unicode_status == UNICODE_ON) {
7257                                 STADJUST(-len, expdest);
7258                                 discard = 0;
7259                                 len = unicode_strlen(p);
7260                         }
7261                 }
7262 #endif
7263                 break;
7264         }
7265
7266         if (discard)
7267                 STADJUST(-len, expdest);
7268         return len;
7269 }
7270
7271 /*
7272  * Expand a variable, and return a pointer to the next character in the
7273  * input string.
7274  */
7275 static char *
7276 evalvar(char *p, int flag)
7277 {
7278         char varflags;
7279         char subtype;
7280         int quoted;
7281         char easy;
7282         char *var;
7283         int patloc;
7284         int startloc;
7285         ssize_t varlen;
7286
7287         varflags = (unsigned char) *p++;
7288         subtype = varflags & VSTYPE;
7289
7290         if (!subtype)
7291                 raise_error_syntax("bad substitution");
7292
7293         quoted = flag & EXP_QUOTED;
7294         var = p;
7295         easy = (!quoted || (*var == '@' && shellparam.nparam));
7296         startloc = expdest - (char *)stackblock();
7297         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7298
7299  again:
7300         varlen = varvalue(var, varflags, flag, &quoted);
7301         if (varflags & VSNUL)
7302                 varlen--;
7303
7304         if (subtype == VSPLUS) {
7305                 varlen = -1 - varlen;
7306                 goto vsplus;
7307         }
7308
7309         if (subtype == VSMINUS) {
7310  vsplus:
7311                 if (varlen < 0) {
7312                         argstr(
7313                                 p,
7314                                 flag | EXP_TILDE | EXP_WORD
7315                         );
7316                         goto end;
7317                 }
7318                 goto record;
7319         }
7320
7321         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7322                 if (varlen >= 0)
7323                         goto record;
7324
7325                 subevalvar(p, var, 0, subtype, startloc, varflags,
7326                            flag & ~QUOTES_ESC);
7327                 varflags &= ~VSNUL;
7328                 /*
7329                  * Remove any recorded regions beyond
7330                  * start of variable
7331                  */
7332                 removerecordregions(startloc);
7333                 goto again;
7334         }
7335
7336         if (varlen < 0 && uflag)
7337                 varunset(p, var, 0, 0);
7338
7339         if (subtype == VSLENGTH) {
7340                 cvtnum(varlen > 0 ? varlen : 0);
7341                 goto record;
7342         }
7343
7344         if (subtype == VSNORMAL) {
7345  record:
7346                 if (!easy)
7347                         goto end;
7348                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7349                 goto end;
7350         }
7351
7352 #if DEBUG
7353         switch (subtype) {
7354         case VSTRIMLEFT:
7355         case VSTRIMLEFTMAX:
7356         case VSTRIMRIGHT:
7357         case VSTRIMRIGHTMAX:
7358 #if BASH_SUBSTR
7359         case VSSUBSTR:
7360 #endif
7361 #if BASH_PATTERN_SUBST
7362         case VSREPLACE:
7363         case VSREPLACEALL:
7364 #endif
7365                 break;
7366         default:
7367                 abort();
7368         }
7369 #endif
7370
7371         if (varlen >= 0) {
7372                 /*
7373                  * Terminate the string and start recording the pattern
7374                  * right after it
7375                  */
7376                 STPUTC('\0', expdest);
7377                 patloc = expdest - (char *)stackblock();
7378                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7379                                 startloc, varflags, flag)) {
7380                         int amount = expdest - (
7381                                 (char *)stackblock() + patloc - 1
7382                         );
7383                         STADJUST(-amount, expdest);
7384                 }
7385                 /* Remove any recorded regions beyond start of variable */
7386                 removerecordregions(startloc);
7387                 goto record;
7388         }
7389
7390  end:
7391         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7392                 int nesting = 1;
7393                 for (;;) {
7394                         unsigned char c = *p++;
7395                         if (c == CTLESC)
7396                                 p++;
7397                         else if (c == CTLBACKQ) {
7398                                 if (varlen >= 0)
7399                                         argbackq = argbackq->next;
7400                         } else if (c == CTLVAR) {
7401                                 if ((*p++ & VSTYPE) != VSNORMAL)
7402                                         nesting++;
7403                         } else if (c == CTLENDVAR) {
7404                                 if (--nesting == 0)
7405                                         break;
7406                         }
7407                 }
7408         }
7409         return p;
7410 }
7411
7412 /*
7413  * Add a file name to the list.
7414  */
7415 static void
7416 addfname(const char *name)
7417 {
7418         struct strlist *sp;
7419
7420         sp = stzalloc(sizeof(*sp));
7421         sp->text = sstrdup(name);
7422         *exparg.lastp = sp;
7423         exparg.lastp = &sp->next;
7424 }
7425
7426 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7427 static int
7428 hasmeta(const char *p)
7429 {
7430         static const char chars[] ALIGN1 = {
7431                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7432         };
7433
7434         for (;;) {
7435                 p = strpbrk(p, chars);
7436                 if (!p)
7437                         break;
7438                 switch ((unsigned char)*p) {
7439                 case CTLQUOTEMARK:
7440                         for (;;) {
7441                                 p++;
7442                                 if ((unsigned char)*p == CTLQUOTEMARK)
7443                                         break;
7444                                 if ((unsigned char)*p == CTLESC)
7445                                         p++;
7446                                 if (*p == '\0') /* huh? */
7447                                         return 0;
7448                         }
7449                         break;
7450                 case '\\':
7451                 case CTLESC:
7452                         p++;
7453                         if (*p == '\0')
7454                                 return 0;
7455                         break;
7456                 case '[':
7457                         if (!strchr(p + 1, ']')) {
7458                                 /* It's not a properly closed [] pattern,
7459                                  * but other metas may follow. Continue checking.
7460                                  * my[file* _is_ globbed by bash
7461                                  * and matches filenames like "my[file1".
7462                                  */
7463                                 break;
7464                         }
7465                         /* fallthrough */
7466                 default:
7467                 /* case '*': */
7468                 /* case '?': */
7469                         return 1;
7470                 }
7471                 p++;
7472         }
7473
7474         return 0;
7475 }
7476
7477 /* If we want to use glob() from libc... */
7478 #if !ENABLE_ASH_INTERNAL_GLOB
7479
7480 /* Add the result of glob() to the list */
7481 static void
7482 addglob(const glob_t *pglob)
7483 {
7484         char **p = pglob->gl_pathv;
7485
7486         do {
7487                 addfname(*p);
7488         } while (*++p);
7489 }
7490 static void
7491 expandmeta(struct strlist *str /*, int flag*/)
7492 {
7493         /* TODO - EXP_REDIR */
7494
7495         while (str) {
7496                 char *p;
7497                 glob_t pglob;
7498                 int i;
7499
7500                 if (fflag)
7501                         goto nometa;
7502
7503                 if (!hasmeta(str->text))
7504                         goto nometa;
7505
7506                 INT_OFF;
7507                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7508 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7509 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7510 //
7511 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7512 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7513 // Which means you need to unescape the string, right? Not so fast:
7514 // if there _is_ a file named "file\?" (with backslash), it is returned
7515 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7516 // You DON'T KNOW by looking at the result whether you need to unescape it.
7517 //
7518 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7519 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7520 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7521 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7522 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7523 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7524                 i = glob(p, 0, NULL, &pglob);
7525                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7526                 if (p != str->text)
7527                         free(p);
7528                 switch (i) {
7529                 case 0:
7530 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7531                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7532                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7533                                 goto nometa2;
7534 #endif
7535                         addglob(&pglob);
7536                         globfree(&pglob);
7537                         INT_ON;
7538                         break;
7539                 case GLOB_NOMATCH:
7540  //nometa2:
7541                         globfree(&pglob);
7542                         INT_ON;
7543  nometa:
7544                         *exparg.lastp = str;
7545                         rmescapes(str->text, 0, NULL);
7546                         exparg.lastp = &str->next;
7547                         break;
7548                 default:        /* GLOB_NOSPACE */
7549                         globfree(&pglob);
7550                         INT_ON;
7551                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7552                 }
7553                 str = str->next;
7554         }
7555 }
7556
7557 #else
7558 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7559
7560 /*
7561  * Do metacharacter (i.e. *, ?, [...]) expansion.
7562  */
7563 static void
7564 expmeta(char *expdir, char *enddir, char *name)
7565 {
7566         char *p;
7567         const char *cp;
7568         char *start;
7569         char *endname;
7570         int metaflag;
7571         struct stat statb;
7572         DIR *dirp;
7573         struct dirent *dp;
7574         int atend;
7575         int matchdot;
7576         int esc;
7577
7578         metaflag = 0;
7579         start = name;
7580         for (p = name; esc = 0, *p; p += esc + 1) {
7581                 if (*p == '*' || *p == '?')
7582                         metaflag = 1;
7583                 else if (*p == '[') {
7584                         char *q = p + 1;
7585                         if (*q == '!')
7586                                 q++;
7587                         for (;;) {
7588                                 if (*q == '\\')
7589                                         q++;
7590                                 if (*q == '/' || *q == '\0')
7591                                         break;
7592                                 if (*++q == ']') {
7593                                         metaflag = 1;
7594                                         break;
7595                                 }
7596                         }
7597                 } else {
7598                         if (*p == '\\')
7599                                 esc++;
7600                         if (p[esc] == '/') {
7601                                 if (metaflag)
7602                                         break;
7603                                 start = p + esc + 1;
7604                         }
7605                 }
7606         }
7607         if (metaflag == 0) {    /* we've reached the end of the file name */
7608                 if (enddir != expdir)
7609                         metaflag++;
7610                 p = name;
7611                 do {
7612                         if (*p == '\\')
7613                                 p++;
7614                         *enddir++ = *p;
7615                 } while (*p++);
7616                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7617                         addfname(expdir);
7618                 return;
7619         }
7620         endname = p;
7621         if (name < start) {
7622                 p = name;
7623                 do {
7624                         if (*p == '\\')
7625                                 p++;
7626                         *enddir++ = *p++;
7627                 } while (p < start);
7628         }
7629         if (enddir == expdir) {
7630                 cp = ".";
7631         } else if (enddir == expdir + 1 && *expdir == '/') {
7632                 cp = "/";
7633         } else {
7634                 cp = expdir;
7635                 enddir[-1] = '\0';
7636         }
7637         dirp = opendir(cp);
7638         if (dirp == NULL)
7639                 return;
7640         if (enddir != expdir)
7641                 enddir[-1] = '/';
7642         if (*endname == 0) {
7643                 atend = 1;
7644         } else {
7645                 atend = 0;
7646                 *endname = '\0';
7647                 endname += esc + 1;
7648         }
7649         matchdot = 0;
7650         p = start;
7651         if (*p == '\\')
7652                 p++;
7653         if (*p == '.')
7654                 matchdot++;
7655         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7656                 if (dp->d_name[0] == '.' && !matchdot)
7657                         continue;
7658                 if (pmatch(start, dp->d_name)) {
7659                         if (atend) {
7660                                 strcpy(enddir, dp->d_name);
7661                                 addfname(expdir);
7662                         } else {
7663                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7664                                         continue;
7665                                 p[-1] = '/';
7666                                 expmeta(expdir, p, endname);
7667                         }
7668                 }
7669         }
7670         closedir(dirp);
7671         if (!atend)
7672                 endname[-esc - 1] = esc ? '\\' : '/';
7673 }
7674
7675 static struct strlist *
7676 msort(struct strlist *list, int len)
7677 {
7678         struct strlist *p, *q = NULL;
7679         struct strlist **lpp;
7680         int half;
7681         int n;
7682
7683         if (len <= 1)
7684                 return list;
7685         half = len >> 1;
7686         p = list;
7687         for (n = half; --n >= 0;) {
7688                 q = p;
7689                 p = p->next;
7690         }
7691         q->next = NULL;                 /* terminate first half of list */
7692         q = msort(list, half);          /* sort first half of list */
7693         p = msort(p, len - half);               /* sort second half */
7694         lpp = &list;
7695         for (;;) {
7696 #if ENABLE_LOCALE_SUPPORT
7697                 if (strcoll(p->text, q->text) < 0)
7698 #else
7699                 if (strcmp(p->text, q->text) < 0)
7700 #endif
7701                                                 {
7702                         *lpp = p;
7703                         lpp = &p->next;
7704                         p = *lpp;
7705                         if (p == NULL) {
7706                                 *lpp = q;
7707                                 break;
7708                         }
7709                 } else {
7710                         *lpp = q;
7711                         lpp = &q->next;
7712                         q = *lpp;
7713                         if (q == NULL) {
7714                                 *lpp = p;
7715                                 break;
7716                         }
7717                 }
7718         }
7719         return list;
7720 }
7721
7722 /*
7723  * Sort the results of file name expansion.  It calculates the number of
7724  * strings to sort and then calls msort (short for merge sort) to do the
7725  * work.
7726  */
7727 static struct strlist *
7728 expsort(struct strlist *str)
7729 {
7730         int len;
7731         struct strlist *sp;
7732
7733         len = 0;
7734         for (sp = str; sp; sp = sp->next)
7735                 len++;
7736         return msort(str, len);
7737 }
7738
7739 static void
7740 expandmeta(struct strlist *str /*, int flag*/)
7741 {
7742         /* TODO - EXP_REDIR */
7743
7744         while (str) {
7745                 char *expdir;
7746                 struct strlist **savelastp;
7747                 struct strlist *sp;
7748                 char *p;
7749
7750                 if (fflag)
7751                         goto nometa;
7752                 if (!hasmeta(str->text))
7753                         goto nometa;
7754                 savelastp = exparg.lastp;
7755
7756                 INT_OFF;
7757                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7758                 {
7759                         int i = strlen(str->text);
7760 //BUGGY estimation of how long expanded name can be
7761                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7762                 }
7763                 expmeta(expdir, expdir, p);
7764                 free(expdir);
7765                 if (p != str->text)
7766                         free(p);
7767                 INT_ON;
7768                 if (exparg.lastp == savelastp) {
7769                         /*
7770                          * no matches
7771                          */
7772  nometa:
7773                         *exparg.lastp = str;
7774                         rmescapes(str->text, 0, NULL);
7775                         exparg.lastp = &str->next;
7776                 } else {
7777                         *exparg.lastp = NULL;
7778                         *savelastp = sp = expsort(*savelastp);
7779                         while (sp->next != NULL)
7780                                 sp = sp->next;
7781                         exparg.lastp = &sp->next;
7782                 }
7783                 str = str->next;
7784         }
7785 }
7786 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7787
7788 /*
7789  * Perform variable substitution and command substitution on an argument,
7790  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7791  * perform splitting and file name expansion.  When arglist is NULL, perform
7792  * here document expansion.
7793  */
7794 static void
7795 expandarg(union node *arg, struct arglist *arglist, int flag)
7796 {
7797         struct strlist *sp;
7798         char *p;
7799
7800         argbackq = arg->narg.backquote;
7801         STARTSTACKSTR(expdest);
7802         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7803         argstr(arg->narg.text, flag);
7804         p = _STPUTC('\0', expdest);
7805         expdest = p - 1;
7806         if (arglist == NULL) {
7807                 /* here document expanded */
7808                 goto out;
7809         }
7810         p = grabstackstr(p);
7811         TRACE(("expandarg: p:'%s'\n", p));
7812         exparg.lastp = &exparg.list;
7813         /*
7814          * TODO - EXP_REDIR
7815          */
7816         if (flag & EXP_FULL) {
7817                 ifsbreakup(p, &exparg);
7818                 *exparg.lastp = NULL;
7819                 exparg.lastp = &exparg.list;
7820                 expandmeta(exparg.list /*, flag*/);
7821         } else {
7822                 sp = stzalloc(sizeof(*sp));
7823                 sp->text = p;
7824                 *exparg.lastp = sp;
7825                 exparg.lastp = &sp->next;
7826         }
7827         *exparg.lastp = NULL;
7828         if (exparg.list) {
7829                 *arglist->lastp = exparg.list;
7830                 arglist->lastp = exparg.lastp;
7831         }
7832
7833  out:
7834         ifsfree();
7835 }
7836
7837 /*
7838  * Expand shell variables and backquotes inside a here document.
7839  */
7840 static void
7841 expandhere(union node *arg, int fd)
7842 {
7843         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7844         full_write(fd, stackblock(), expdest - (char *)stackblock());
7845 }
7846
7847 /*
7848  * Returns true if the pattern matches the string.
7849  */
7850 static int
7851 patmatch(char *pattern, const char *string)
7852 {
7853         char *p = preglob(pattern, 0);
7854         int r = pmatch(p, string);
7855         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7856         return r;
7857 }
7858
7859 /*
7860  * See if a pattern matches in a case statement.
7861  */
7862 static int
7863 casematch(union node *pattern, char *val)
7864 {
7865         struct stackmark smark;
7866         int result;
7867
7868         setstackmark(&smark);
7869         argbackq = pattern->narg.backquote;
7870         STARTSTACKSTR(expdest);
7871         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7872         STACKSTRNUL(expdest);
7873         ifsfree();
7874         result = patmatch(stackblock(), val);
7875         popstackmark(&smark);
7876         return result;
7877 }
7878
7879
7880 /* ============ find_command */
7881
7882 struct builtincmd {
7883         const char *name;
7884         int (*builtin)(int, char **) FAST_FUNC;
7885         /* unsigned flags; */
7886 };
7887 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7888 /* "regular" builtins always take precedence over commands,
7889  * regardless of PATH=....%builtin... position */
7890 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7891 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7892
7893 struct cmdentry {
7894         smallint cmdtype;       /* CMDxxx */
7895         union param {
7896                 int index;
7897                 /* index >= 0 for commands without path (slashes) */
7898                 /* (TODO: what exactly does the value mean? PATH position?) */
7899                 /* index == -1 for commands with slashes */
7900                 /* index == (-2 - applet_no) for NOFORK applets */
7901                 const struct builtincmd *cmd;
7902                 struct funcnode *func;
7903         } u;
7904 };
7905 /* values of cmdtype */
7906 #define CMDUNKNOWN      -1      /* no entry in table for command */
7907 #define CMDNORMAL       0       /* command is an executable program */
7908 #define CMDFUNCTION     1       /* command is a shell function */
7909 #define CMDBUILTIN      2       /* command is a shell builtin */
7910
7911 /* action to find_command() */
7912 #define DO_ERR          0x01    /* prints errors */
7913 #define DO_ABS          0x02    /* checks absolute paths */
7914 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7915 #define DO_ALTPATH      0x08    /* using alternate path */
7916 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7917
7918 static void find_command(char *, struct cmdentry *, int, const char *);
7919
7920
7921 /* ============ Hashing commands */
7922
7923 /*
7924  * When commands are first encountered, they are entered in a hash table.
7925  * This ensures that a full path search will not have to be done for them
7926  * on each invocation.
7927  *
7928  * We should investigate converting to a linear search, even though that
7929  * would make the command name "hash" a misnomer.
7930  */
7931
7932 struct tblentry {
7933         struct tblentry *next;  /* next entry in hash chain */
7934         union param param;      /* definition of builtin function */
7935         smallint cmdtype;       /* CMDxxx */
7936         char rehash;            /* if set, cd done since entry created */
7937         char cmdname[1];        /* name of command */
7938 };
7939
7940 static struct tblentry **cmdtable;
7941 #define INIT_G_cmdtable() do { \
7942         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7943 } while (0)
7944
7945 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7946
7947
7948 static void
7949 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7950 {
7951 #if ENABLE_FEATURE_SH_STANDALONE
7952         if (applet_no >= 0) {
7953                 if (APPLET_IS_NOEXEC(applet_no)) {
7954                         clearenv();
7955                         while (*envp)
7956                                 putenv(*envp++);
7957                         popredir(/*drop:*/ 1);
7958                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7959                 }
7960                 /* re-exec ourselves with the new arguments */
7961                 execve(bb_busybox_exec_path, argv, envp);
7962                 /* If they called chroot or otherwise made the binary no longer
7963                  * executable, fall through */
7964         }
7965 #endif
7966
7967  repeat:
7968 #ifdef SYSV
7969         do {
7970                 execve(cmd, argv, envp);
7971         } while (errno == EINTR);
7972 #else
7973         execve(cmd, argv, envp);
7974 #endif
7975         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7976                 /* Run "cmd" as a shell script:
7977                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7978                  * "If the execve() function fails with ENOEXEC, the shell
7979                  * shall execute a command equivalent to having a shell invoked
7980                  * with the command name as its first operand,
7981                  * with any remaining arguments passed to the new shell"
7982                  *
7983                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7984                  * just call ourselves.
7985                  *
7986                  * Note that bash reads ~80 chars of the file, and if it sees
7987                  * a zero byte before it sees newline, it doesn't try to
7988                  * interpret it, but fails with "cannot execute binary file"
7989                  * message and exit code 126. For one, this prevents attempts
7990                  * to interpret foreign ELF binaries as shell scripts.
7991                  */
7992                 argv[0] = (char*) cmd;
7993                 cmd = bb_busybox_exec_path;
7994                 /* NB: this is only possible because all callers of shellexec()
7995                  * ensure that the argv[-1] slot exists!
7996                  */
7997                 argv--;
7998                 argv[0] = (char*) "ash";
7999                 goto repeat;
8000         }
8001 }
8002
8003 /*
8004  * Exec a program.  Never returns.  If you change this routine, you may
8005  * have to change the find_command routine as well.
8006  * argv[-1] must exist and be writable! See tryexec() for why.
8007  */
8008 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8009 static void shellexec(char *prog, char **argv, const char *path, int idx)
8010 {
8011         char *cmdname;
8012         int e;
8013         char **envp;
8014         int exerrno;
8015         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8016
8017         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8018         if (strchr(prog, '/') != NULL
8019 #if ENABLE_FEATURE_SH_STANDALONE
8020          || (applet_no = find_applet_by_name(prog)) >= 0
8021 #endif
8022         ) {
8023                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8024                 if (applet_no >= 0) {
8025                         /* We tried execing ourself, but it didn't work.
8026                          * Maybe /proc/self/exe doesn't exist?
8027                          * Try $PATH search.
8028                          */
8029                         goto try_PATH;
8030                 }
8031                 e = errno;
8032         } else {
8033  try_PATH:
8034                 e = ENOENT;
8035                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8036                         if (--idx < 0 && pathopt == NULL) {
8037                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8038                                 if (errno != ENOENT && errno != ENOTDIR)
8039                                         e = errno;
8040                         }
8041                         stunalloc(cmdname);
8042                 }
8043         }
8044
8045         /* Map to POSIX errors */
8046         switch (e) {
8047         case EACCES:
8048                 exerrno = 126;
8049                 break;
8050         case ENOENT:
8051                 exerrno = 127;
8052                 break;
8053         default:
8054                 exerrno = 2;
8055                 break;
8056         }
8057         exitstatus = exerrno;
8058         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8059                 prog, e, suppress_int));
8060         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8061         /* NOTREACHED */
8062 }
8063
8064 static void
8065 printentry(struct tblentry *cmdp)
8066 {
8067         int idx;
8068         const char *path;
8069         char *name;
8070
8071         idx = cmdp->param.index;
8072         path = pathval();
8073         do {
8074                 name = path_advance(&path, cmdp->cmdname);
8075                 stunalloc(name);
8076         } while (--idx >= 0);
8077         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8078 }
8079
8080 /*
8081  * Clear out command entries.  The argument specifies the first entry in
8082  * PATH which has changed.
8083  */
8084 static void
8085 clearcmdentry(int firstchange)
8086 {
8087         struct tblentry **tblp;
8088         struct tblentry **pp;
8089         struct tblentry *cmdp;
8090
8091         INT_OFF;
8092         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8093                 pp = tblp;
8094                 while ((cmdp = *pp) != NULL) {
8095                         if ((cmdp->cmdtype == CMDNORMAL &&
8096                              cmdp->param.index >= firstchange)
8097                          || (cmdp->cmdtype == CMDBUILTIN &&
8098                              builtinloc >= firstchange)
8099                         ) {
8100                                 *pp = cmdp->next;
8101                                 free(cmdp);
8102                         } else {
8103                                 pp = &cmdp->next;
8104                         }
8105                 }
8106         }
8107         INT_ON;
8108 }
8109
8110 /*
8111  * Locate a command in the command hash table.  If "add" is nonzero,
8112  * add the command to the table if it is not already present.  The
8113  * variable "lastcmdentry" is set to point to the address of the link
8114  * pointing to the entry, so that delete_cmd_entry can delete the
8115  * entry.
8116  *
8117  * Interrupts must be off if called with add != 0.
8118  */
8119 static struct tblentry **lastcmdentry;
8120
8121 static struct tblentry *
8122 cmdlookup(const char *name, int add)
8123 {
8124         unsigned int hashval;
8125         const char *p;
8126         struct tblentry *cmdp;
8127         struct tblentry **pp;
8128
8129         p = name;
8130         hashval = (unsigned char)*p << 4;
8131         while (*p)
8132                 hashval += (unsigned char)*p++;
8133         hashval &= 0x7FFF;
8134         pp = &cmdtable[hashval % CMDTABLESIZE];
8135         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8136                 if (strcmp(cmdp->cmdname, name) == 0)
8137                         break;
8138                 pp = &cmdp->next;
8139         }
8140         if (add && cmdp == NULL) {
8141                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8142                                 + strlen(name)
8143                                 /* + 1 - already done because
8144                                  * tblentry::cmdname is char[1] */);
8145                 /*cmdp->next = NULL; - ckzalloc did it */
8146                 cmdp->cmdtype = CMDUNKNOWN;
8147                 strcpy(cmdp->cmdname, name);
8148         }
8149         lastcmdentry = pp;
8150         return cmdp;
8151 }
8152
8153 /*
8154  * Delete the command entry returned on the last lookup.
8155  */
8156 static void
8157 delete_cmd_entry(void)
8158 {
8159         struct tblentry *cmdp;
8160
8161         INT_OFF;
8162         cmdp = *lastcmdentry;
8163         *lastcmdentry = cmdp->next;
8164         if (cmdp->cmdtype == CMDFUNCTION)
8165                 freefunc(cmdp->param.func);
8166         free(cmdp);
8167         INT_ON;
8168 }
8169
8170 /*
8171  * Add a new command entry, replacing any existing command entry for
8172  * the same name - except special builtins.
8173  */
8174 static void
8175 addcmdentry(char *name, struct cmdentry *entry)
8176 {
8177         struct tblentry *cmdp;
8178
8179         cmdp = cmdlookup(name, 1);
8180         if (cmdp->cmdtype == CMDFUNCTION) {
8181                 freefunc(cmdp->param.func);
8182         }
8183         cmdp->cmdtype = entry->cmdtype;
8184         cmdp->param = entry->u;
8185         cmdp->rehash = 0;
8186 }
8187
8188 static int FAST_FUNC
8189 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8190 {
8191         struct tblentry **pp;
8192         struct tblentry *cmdp;
8193         int c;
8194         struct cmdentry entry;
8195         char *name;
8196
8197         if (nextopt("r") != '\0') {
8198                 clearcmdentry(0);
8199                 return 0;
8200         }
8201
8202         if (*argptr == NULL) {
8203                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8204                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8205                                 if (cmdp->cmdtype == CMDNORMAL)
8206                                         printentry(cmdp);
8207                         }
8208                 }
8209                 return 0;
8210         }
8211
8212         c = 0;
8213         while ((name = *argptr) != NULL) {
8214                 cmdp = cmdlookup(name, 0);
8215                 if (cmdp != NULL
8216                  && (cmdp->cmdtype == CMDNORMAL
8217                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8218                 ) {
8219                         delete_cmd_entry();
8220                 }
8221                 find_command(name, &entry, DO_ERR, pathval());
8222                 if (entry.cmdtype == CMDUNKNOWN)
8223                         c = 1;
8224                 argptr++;
8225         }
8226         return c;
8227 }
8228
8229 /*
8230  * Called when a cd is done.  Marks all commands so the next time they
8231  * are executed they will be rehashed.
8232  */
8233 static void
8234 hashcd(void)
8235 {
8236         struct tblentry **pp;
8237         struct tblentry *cmdp;
8238
8239         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8240                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8241                         if (cmdp->cmdtype == CMDNORMAL
8242                          || (cmdp->cmdtype == CMDBUILTIN
8243                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8244                              && builtinloc > 0)
8245                         ) {
8246                                 cmdp->rehash = 1;
8247                         }
8248                 }
8249         }
8250 }
8251
8252 /*
8253  * Fix command hash table when PATH changed.
8254  * Called before PATH is changed.  The argument is the new value of PATH;
8255  * pathval() still returns the old value at this point.
8256  * Called with interrupts off.
8257  */
8258 static void FAST_FUNC
8259 changepath(const char *new)
8260 {
8261         const char *old;
8262         int firstchange;
8263         int idx;
8264         int idx_bltin;
8265
8266         old = pathval();
8267         firstchange = 9999;     /* assume no change */
8268         idx = 0;
8269         idx_bltin = -1;
8270         for (;;) {
8271                 if (*old != *new) {
8272                         firstchange = idx;
8273                         if ((*old == '\0' && *new == ':')
8274                          || (*old == ':' && *new == '\0')
8275                         ) {
8276                                 firstchange++;
8277                         }
8278                         old = new;      /* ignore subsequent differences */
8279                 }
8280                 if (*new == '\0')
8281                         break;
8282                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8283                         idx_bltin = idx;
8284                 if (*new == ':')
8285                         idx++;
8286                 new++;
8287                 old++;
8288         }
8289         if (builtinloc < 0 && idx_bltin >= 0)
8290                 builtinloc = idx_bltin;             /* zap builtins */
8291         if (builtinloc >= 0 && idx_bltin < 0)
8292                 firstchange = 0;
8293         clearcmdentry(firstchange);
8294         builtinloc = idx_bltin;
8295 }
8296 enum {
8297         TEOF,
8298         TNL,
8299         TREDIR,
8300         TWORD,
8301         TSEMI,
8302         TBACKGND,
8303         TAND,
8304         TOR,
8305         TPIPE,
8306         TLP,
8307         TRP,
8308         TENDCASE,
8309         TENDBQUOTE,
8310         TNOT,
8311         TCASE,
8312         TDO,
8313         TDONE,
8314         TELIF,
8315         TELSE,
8316         TESAC,
8317         TFI,
8318         TFOR,
8319 #if BASH_FUNCTION
8320         TFUNCTION,
8321 #endif
8322         TIF,
8323         TIN,
8324         TTHEN,
8325         TUNTIL,
8326         TWHILE,
8327         TBEGIN,
8328         TEND
8329 };
8330 typedef smallint token_id_t;
8331
8332 /* Nth bit indicates if token marks the end of a list */
8333 enum {
8334         tokendlist = 0
8335         /*  0 */ | (1u << TEOF)
8336         /*  1 */ | (0u << TNL)
8337         /*  2 */ | (0u << TREDIR)
8338         /*  3 */ | (0u << TWORD)
8339         /*  4 */ | (0u << TSEMI)
8340         /*  5 */ | (0u << TBACKGND)
8341         /*  6 */ | (0u << TAND)
8342         /*  7 */ | (0u << TOR)
8343         /*  8 */ | (0u << TPIPE)
8344         /*  9 */ | (0u << TLP)
8345         /* 10 */ | (1u << TRP)
8346         /* 11 */ | (1u << TENDCASE)
8347         /* 12 */ | (1u << TENDBQUOTE)
8348         /* 13 */ | (0u << TNOT)
8349         /* 14 */ | (0u << TCASE)
8350         /* 15 */ | (1u << TDO)
8351         /* 16 */ | (1u << TDONE)
8352         /* 17 */ | (1u << TELIF)
8353         /* 18 */ | (1u << TELSE)
8354         /* 19 */ | (1u << TESAC)
8355         /* 20 */ | (1u << TFI)
8356         /* 21 */ | (0u << TFOR)
8357 #if BASH_FUNCTION
8358         /* 22 */ | (0u << TFUNCTION)
8359 #endif
8360         /* 23 */ | (0u << TIF)
8361         /* 24 */ | (0u << TIN)
8362         /* 25 */ | (1u << TTHEN)
8363         /* 26 */ | (0u << TUNTIL)
8364         /* 27 */ | (0u << TWHILE)
8365         /* 28 */ | (0u << TBEGIN)
8366         /* 29 */ | (1u << TEND)
8367         , /* thus far 29 bits used */
8368 };
8369
8370 static const char *const tokname_array[] = {
8371         "end of file",
8372         "newline",
8373         "redirection",
8374         "word",
8375         ";",
8376         "&",
8377         "&&",
8378         "||",
8379         "|",
8380         "(",
8381         ")",
8382         ";;",
8383         "`",
8384 #define KWDOFFSET 13
8385         /* the following are keywords */
8386         "!",
8387         "case",
8388         "do",
8389         "done",
8390         "elif",
8391         "else",
8392         "esac",
8393         "fi",
8394         "for",
8395 #if BASH_FUNCTION
8396         "function",
8397 #endif
8398         "if",
8399         "in",
8400         "then",
8401         "until",
8402         "while",
8403         "{",
8404         "}",
8405 };
8406
8407 /* Wrapper around strcmp for qsort/bsearch/... */
8408 static int
8409 pstrcmp(const void *a, const void *b)
8410 {
8411         return strcmp((char*)a, *(char**)b);
8412 }
8413
8414 static const char *const *
8415 findkwd(const char *s)
8416 {
8417         return bsearch(s, tokname_array + KWDOFFSET,
8418                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8419                         sizeof(tokname_array[0]), pstrcmp);
8420 }
8421
8422 /*
8423  * Locate and print what a word is...
8424  */
8425 static int
8426 describe_command(char *command, const char *path, int describe_command_verbose)
8427 {
8428         struct cmdentry entry;
8429 #if ENABLE_ASH_ALIAS
8430         const struct alias *ap;
8431 #endif
8432
8433         path = path ? path : pathval();
8434
8435         if (describe_command_verbose) {
8436                 out1str(command);
8437         }
8438
8439         /* First look at the keywords */
8440         if (findkwd(command)) {
8441                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8442                 goto out;
8443         }
8444
8445 #if ENABLE_ASH_ALIAS
8446         /* Then look at the aliases */
8447         ap = lookupalias(command, 0);
8448         if (ap != NULL) {
8449                 if (!describe_command_verbose) {
8450                         out1str("alias ");
8451                         printalias(ap);
8452                         return 0;
8453                 }
8454                 out1fmt(" is an alias for %s", ap->val);
8455                 goto out;
8456         }
8457 #endif
8458         /* Brute force */
8459         find_command(command, &entry, DO_ABS, path);
8460
8461         switch (entry.cmdtype) {
8462         case CMDNORMAL: {
8463                 int j = entry.u.index;
8464                 char *p;
8465                 if (j < 0) {
8466                         p = command;
8467                 } else {
8468                         do {
8469                                 p = path_advance(&path, command);
8470                                 stunalloc(p);
8471                         } while (--j >= 0);
8472                 }
8473                 if (describe_command_verbose) {
8474                         out1fmt(" is %s", p);
8475                 } else {
8476                         out1str(p);
8477                 }
8478                 break;
8479         }
8480
8481         case CMDFUNCTION:
8482                 if (describe_command_verbose) {
8483                         out1str(" is a shell function");
8484                 } else {
8485                         out1str(command);
8486                 }
8487                 break;
8488
8489         case CMDBUILTIN:
8490                 if (describe_command_verbose) {
8491                         out1fmt(" is a %sshell builtin",
8492                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8493                                         "special " : nullstr
8494                         );
8495                 } else {
8496                         out1str(command);
8497                 }
8498                 break;
8499
8500         default:
8501                 if (describe_command_verbose) {
8502                         out1str(": not found\n");
8503                 }
8504                 return 127;
8505         }
8506  out:
8507         out1str("\n");
8508         return 0;
8509 }
8510
8511 static int FAST_FUNC
8512 typecmd(int argc UNUSED_PARAM, char **argv)
8513 {
8514         int i = 1;
8515         int err = 0;
8516         int verbose = 1;
8517
8518         /* type -p ... ? (we don't bother checking for 'p') */
8519         if (argv[1] && argv[1][0] == '-') {
8520                 i++;
8521                 verbose = 0;
8522         }
8523         while (argv[i]) {
8524                 err |= describe_command(argv[i++], NULL, verbose);
8525         }
8526         return err;
8527 }
8528
8529 #if ENABLE_ASH_CMDCMD
8530 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8531 static char **
8532 parse_command_args(char **argv, const char **path)
8533 {
8534         char *cp, c;
8535
8536         for (;;) {
8537                 cp = *++argv;
8538                 if (!cp)
8539                         return NULL;
8540                 if (*cp++ != '-')
8541                         break;
8542                 c = *cp++;
8543                 if (!c)
8544                         break;
8545                 if (c == '-' && !*cp) {
8546                         if (!*++argv)
8547                                 return NULL;
8548                         break;
8549                 }
8550                 do {
8551                         switch (c) {
8552                         case 'p':
8553                                 *path = bb_default_path;
8554                                 break;
8555                         default:
8556                                 /* run 'typecmd' for other options */
8557                                 return NULL;
8558                         }
8559                         c = *cp++;
8560                 } while (c);
8561         }
8562         return argv;
8563 }
8564
8565 static int FAST_FUNC
8566 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8567 {
8568         char *cmd;
8569         int c;
8570         enum {
8571                 VERIFY_BRIEF = 1,
8572                 VERIFY_VERBOSE = 2,
8573         } verify = 0;
8574         const char *path = NULL;
8575
8576         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8577          * never reaches this function.
8578          */
8579
8580         while ((c = nextopt("pvV")) != '\0')
8581                 if (c == 'V')
8582                         verify |= VERIFY_VERBOSE;
8583                 else if (c == 'v')
8584                         /*verify |= VERIFY_BRIEF*/;
8585 #if DEBUG
8586                 else if (c != 'p')
8587                         abort();
8588 #endif
8589                 else
8590                         path = bb_default_path;
8591
8592         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8593         cmd = *argptr;
8594         if (/*verify && */ cmd)
8595                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8596
8597         return 0;
8598 }
8599 #endif
8600
8601
8602 /*static int funcblocksize;     // size of structures in function */
8603 /*static int funcstringsize;    // size of strings in node */
8604 static void *funcblock;         /* block to allocate function from */
8605 static char *funcstring_end;    /* end of block to allocate strings from */
8606
8607 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8608         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8609         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8610         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8611         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8612         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8613         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8614         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8615         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8616         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8617         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8618         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8619         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8620         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8621         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8622         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8623         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8624         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8625 #if BASH_REDIR_OUTPUT
8626         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8627 #endif
8628         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8629         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8630         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8631         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8632         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8633         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8634         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8635         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8636         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8637 };
8638
8639 static int calcsize(int funcblocksize, union node *n);
8640
8641 static int
8642 sizenodelist(int funcblocksize, struct nodelist *lp)
8643 {
8644         while (lp) {
8645                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8646                 funcblocksize = calcsize(funcblocksize, lp->n);
8647                 lp = lp->next;
8648         }
8649         return funcblocksize;
8650 }
8651
8652 static int
8653 calcsize(int funcblocksize, union node *n)
8654 {
8655         if (n == NULL)
8656                 return funcblocksize;
8657         funcblocksize += nodesize[n->type];
8658         switch (n->type) {
8659         case NCMD:
8660                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8661                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8662                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8663                 break;
8664         case NPIPE:
8665                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8666                 break;
8667         case NREDIR:
8668         case NBACKGND:
8669         case NSUBSHELL:
8670                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8671                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8672                 break;
8673         case NAND:
8674         case NOR:
8675         case NSEMI:
8676         case NWHILE:
8677         case NUNTIL:
8678                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8679                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8680                 break;
8681         case NIF:
8682                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8683                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8684                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8685                 break;
8686         case NFOR:
8687                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8688                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8689                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8690                 break;
8691         case NCASE:
8692                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8693                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8694                 break;
8695         case NCLIST:
8696                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8697                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8698                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8699                 break;
8700         case NDEFUN:
8701                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8702                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8703                 break;
8704         case NARG:
8705                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8706                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8707                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8708                 break;
8709         case NTO:
8710 #if BASH_REDIR_OUTPUT
8711         case NTO2:
8712 #endif
8713         case NCLOBBER:
8714         case NFROM:
8715         case NFROMTO:
8716         case NAPPEND:
8717                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8718                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8719                 break;
8720         case NTOFD:
8721         case NFROMFD:
8722                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8723                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8724         break;
8725         case NHERE:
8726         case NXHERE:
8727                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8728                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8729                 break;
8730         case NNOT:
8731                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8732                 break;
8733         };
8734         return funcblocksize;
8735 }
8736
8737 static char *
8738 nodeckstrdup(char *s)
8739 {
8740         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8741         return strcpy(funcstring_end, s);
8742 }
8743
8744 static union node *copynode(union node *);
8745
8746 static struct nodelist *
8747 copynodelist(struct nodelist *lp)
8748 {
8749         struct nodelist *start;
8750         struct nodelist **lpp;
8751
8752         lpp = &start;
8753         while (lp) {
8754                 *lpp = funcblock;
8755                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8756                 (*lpp)->n = copynode(lp->n);
8757                 lp = lp->next;
8758                 lpp = &(*lpp)->next;
8759         }
8760         *lpp = NULL;
8761         return start;
8762 }
8763
8764 static union node *
8765 copynode(union node *n)
8766 {
8767         union node *new;
8768
8769         if (n == NULL)
8770                 return NULL;
8771         new = funcblock;
8772         funcblock = (char *) funcblock + nodesize[n->type];
8773
8774         switch (n->type) {
8775         case NCMD:
8776                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8777                 new->ncmd.args = copynode(n->ncmd.args);
8778                 new->ncmd.assign = copynode(n->ncmd.assign);
8779                 new->ncmd.linno = n->ncmd.linno;
8780                 break;
8781         case NPIPE:
8782                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8783                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8784                 break;
8785         case NREDIR:
8786         case NBACKGND:
8787         case NSUBSHELL:
8788                 new->nredir.redirect = copynode(n->nredir.redirect);
8789                 new->nredir.n = copynode(n->nredir.n);
8790                 new->nredir.linno = n->nredir.linno;
8791                 break;
8792         case NAND:
8793         case NOR:
8794         case NSEMI:
8795         case NWHILE:
8796         case NUNTIL:
8797                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8798                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8799                 break;
8800         case NIF:
8801                 new->nif.elsepart = copynode(n->nif.elsepart);
8802                 new->nif.ifpart = copynode(n->nif.ifpart);
8803                 new->nif.test = copynode(n->nif.test);
8804                 break;
8805         case NFOR:
8806                 new->nfor.var = nodeckstrdup(n->nfor.var);
8807                 new->nfor.body = copynode(n->nfor.body);
8808                 new->nfor.args = copynode(n->nfor.args);
8809                 new->nfor.linno = n->nfor.linno;
8810                 break;
8811         case NCASE:
8812                 new->ncase.cases = copynode(n->ncase.cases);
8813                 new->ncase.expr = copynode(n->ncase.expr);
8814                 new->ncase.linno = n->ncase.linno;
8815                 break;
8816         case NCLIST:
8817                 new->nclist.body = copynode(n->nclist.body);
8818                 new->nclist.pattern = copynode(n->nclist.pattern);
8819                 new->nclist.next = copynode(n->nclist.next);
8820                 break;
8821         case NDEFUN:
8822                 new->ndefun.body = copynode(n->ndefun.body);
8823                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8824                 new->ndefun.linno = n->ndefun.linno;
8825                 break;
8826         case NARG:
8827                 new->narg.backquote = copynodelist(n->narg.backquote);
8828                 new->narg.text = nodeckstrdup(n->narg.text);
8829                 new->narg.next = copynode(n->narg.next);
8830                 break;
8831         case NTO:
8832 #if BASH_REDIR_OUTPUT
8833         case NTO2:
8834 #endif
8835         case NCLOBBER:
8836         case NFROM:
8837         case NFROMTO:
8838         case NAPPEND:
8839                 new->nfile.fname = copynode(n->nfile.fname);
8840                 new->nfile.fd = n->nfile.fd;
8841                 new->nfile.next = copynode(n->nfile.next);
8842                 break;
8843         case NTOFD:
8844         case NFROMFD:
8845                 new->ndup.vname = copynode(n->ndup.vname);
8846                 new->ndup.dupfd = n->ndup.dupfd;
8847                 new->ndup.fd = n->ndup.fd;
8848                 new->ndup.next = copynode(n->ndup.next);
8849                 break;
8850         case NHERE:
8851         case NXHERE:
8852                 new->nhere.doc = copynode(n->nhere.doc);
8853                 new->nhere.fd = n->nhere.fd;
8854                 new->nhere.next = copynode(n->nhere.next);
8855                 break;
8856         case NNOT:
8857                 new->nnot.com = copynode(n->nnot.com);
8858                 break;
8859         };
8860         new->type = n->type;
8861         return new;
8862 }
8863
8864 /*
8865  * Make a copy of a parse tree.
8866  */
8867 static struct funcnode *
8868 copyfunc(union node *n)
8869 {
8870         struct funcnode *f;
8871         size_t blocksize;
8872
8873         /*funcstringsize = 0;*/
8874         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8875         f = ckzalloc(blocksize /* + funcstringsize */);
8876         funcblock = (char *) f + offsetof(struct funcnode, n);
8877         funcstring_end = (char *) f + blocksize;
8878         copynode(n);
8879         /* f->count = 0; - ckzalloc did it */
8880         return f;
8881 }
8882
8883 /*
8884  * Define a shell function.
8885  */
8886 static void
8887 defun(union node *func)
8888 {
8889         struct cmdentry entry;
8890
8891         INT_OFF;
8892         entry.cmdtype = CMDFUNCTION;
8893         entry.u.func = copyfunc(func);
8894         addcmdentry(func->ndefun.text, &entry);
8895         INT_ON;
8896 }
8897
8898 /* Reasons for skipping commands (see comment on breakcmd routine) */
8899 #define SKIPBREAK      (1 << 0)
8900 #define SKIPCONT       (1 << 1)
8901 #define SKIPFUNC       (1 << 2)
8902 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8903 static int skipcount;           /* number of levels to skip */
8904 static int loopnest;            /* current loop nesting level */
8905 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8906
8907 /* Forward decl way out to parsing code - dotrap needs it */
8908 static int evalstring(char *s, int flags);
8909
8910 /* Called to execute a trap.
8911  * Single callsite - at the end of evaltree().
8912  * If we return non-zero, evaltree raises EXEXIT exception.
8913  *
8914  * Perhaps we should avoid entering new trap handlers
8915  * while we are executing a trap handler. [is it a TODO?]
8916  */
8917 static void
8918 dotrap(void)
8919 {
8920         uint8_t *g;
8921         int sig;
8922         uint8_t last_status;
8923
8924         if (!pending_sig)
8925                 return;
8926
8927         last_status = exitstatus;
8928         pending_sig = 0;
8929         barrier();
8930
8931         TRACE(("dotrap entered\n"));
8932         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8933                 char *p;
8934
8935                 if (!*g)
8936                         continue;
8937
8938                 if (evalskip) {
8939                         pending_sig = sig;
8940                         break;
8941                 }
8942
8943                 p = trap[sig];
8944                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8945                  * don't upset it by resetting gotsig[SIGINT-1] */
8946                 if (sig == SIGINT && !p)
8947                         continue;
8948
8949                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8950                 *g = 0;
8951                 if (!p)
8952                         continue;
8953                 evalstring(p, 0);
8954         }
8955         exitstatus = last_status;
8956         TRACE(("dotrap returns\n"));
8957 }
8958
8959 /* forward declarations - evaluation is fairly recursive business... */
8960 static int evalloop(union node *, int);
8961 static int evalfor(union node *, int);
8962 static int evalcase(union node *, int);
8963 static int evalsubshell(union node *, int);
8964 static void expredir(union node *);
8965 static int evalpipe(union node *, int);
8966 static int evalcommand(union node *, int);
8967 static int evalbltin(const struct builtincmd *, int, char **, int);
8968 static void prehash(union node *);
8969
8970 /*
8971  * Evaluate a parse tree.  The value is left in the global variable
8972  * exitstatus.
8973  */
8974 static int
8975 evaltree(union node *n, int flags)
8976 {
8977         int checkexit = 0;
8978         int (*evalfn)(union node *, int);
8979         int status = 0;
8980
8981         if (n == NULL) {
8982                 TRACE(("evaltree(NULL) called\n"));
8983                 goto out;
8984         }
8985         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8986
8987         dotrap();
8988
8989         switch (n->type) {
8990         default:
8991 #if DEBUG
8992                 out1fmt("Node type = %d\n", n->type);
8993                 fflush_all();
8994                 break;
8995 #endif
8996         case NNOT:
8997                 status = !evaltree(n->nnot.com, EV_TESTED);
8998                 goto setstatus;
8999         case NREDIR:
9000                 errlinno = lineno = n->nredir.linno;
9001                 if (funcline)
9002                         lineno -= funcline - 1;
9003                 expredir(n->nredir.redirect);
9004                 pushredir(n->nredir.redirect);
9005                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9006                 if (!status) {
9007                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9008                 }
9009                 if (n->nredir.redirect)
9010                         popredir(/*drop:*/ 0);
9011                 goto setstatus;
9012         case NCMD:
9013                 evalfn = evalcommand;
9014  checkexit:
9015                 if (eflag && !(flags & EV_TESTED))
9016                         checkexit = ~0;
9017                 goto calleval;
9018         case NFOR:
9019                 evalfn = evalfor;
9020                 goto calleval;
9021         case NWHILE:
9022         case NUNTIL:
9023                 evalfn = evalloop;
9024                 goto calleval;
9025         case NSUBSHELL:
9026         case NBACKGND:
9027                 evalfn = evalsubshell;
9028                 goto checkexit;
9029         case NPIPE:
9030                 evalfn = evalpipe;
9031                 goto checkexit;
9032         case NCASE:
9033                 evalfn = evalcase;
9034                 goto calleval;
9035         case NAND:
9036         case NOR:
9037         case NSEMI: {
9038
9039 #if NAND + 1 != NOR
9040 #error NAND + 1 != NOR
9041 #endif
9042 #if NOR + 1 != NSEMI
9043 #error NOR + 1 != NSEMI
9044 #endif
9045                 unsigned is_or = n->type - NAND;
9046                 status = evaltree(
9047                         n->nbinary.ch1,
9048                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9049                 );
9050                 if ((!status) == is_or || evalskip)
9051                         break;
9052                 n = n->nbinary.ch2;
9053  evaln:
9054                 evalfn = evaltree;
9055  calleval:
9056                 status = evalfn(n, flags);
9057                 goto setstatus;
9058         }
9059         case NIF:
9060                 status = evaltree(n->nif.test, EV_TESTED);
9061                 if (evalskip)
9062                         break;
9063                 if (!status) {
9064                         n = n->nif.ifpart;
9065                         goto evaln;
9066                 }
9067                 if (n->nif.elsepart) {
9068                         n = n->nif.elsepart;
9069                         goto evaln;
9070                 }
9071                 status = 0;
9072                 goto setstatus;
9073         case NDEFUN:
9074                 defun(n);
9075                 /* Not necessary. To test it:
9076                  * "false; f() { qwerty; }; echo $?" should print 0.
9077                  */
9078                 /* status = 0; */
9079  setstatus:
9080                 exitstatus = status;
9081                 break;
9082         }
9083  out:
9084         /* Order of checks below is important:
9085          * signal handlers trigger before exit caused by "set -e".
9086          */
9087         dotrap();
9088
9089         if (checkexit & status)
9090                 raise_exception(EXEXIT);
9091         if (flags & EV_EXIT)
9092                 raise_exception(EXEXIT);
9093
9094         TRACE(("leaving evaltree (no interrupts)\n"));
9095         return exitstatus;
9096 }
9097
9098 static int
9099 skiploop(void)
9100 {
9101         int skip = evalskip;
9102
9103         switch (skip) {
9104         case 0:
9105                 break;
9106         case SKIPBREAK:
9107         case SKIPCONT:
9108                 if (--skipcount <= 0) {
9109                         evalskip = 0;
9110                         break;
9111                 }
9112                 skip = SKIPBREAK;
9113                 break;
9114         }
9115         return skip;
9116 }
9117
9118 static int
9119 evalloop(union node *n, int flags)
9120 {
9121         int skip;
9122         int status;
9123
9124         loopnest++;
9125         status = 0;
9126         flags &= EV_TESTED;
9127         do {
9128                 int i;
9129
9130                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9131                 skip = skiploop();
9132                 if (skip == SKIPFUNC)
9133                         status = i;
9134                 if (skip)
9135                         continue;
9136                 if (n->type != NWHILE)
9137                         i = !i;
9138                 if (i != 0)
9139                         break;
9140                 status = evaltree(n->nbinary.ch2, flags);
9141                 skip = skiploop();
9142         } while (!(skip & ~SKIPCONT));
9143         loopnest--;
9144
9145         return status;
9146 }
9147
9148 static int
9149 evalfor(union node *n, int flags)
9150 {
9151         struct arglist arglist;
9152         union node *argp;
9153         struct strlist *sp;
9154         struct stackmark smark;
9155         int status = 0;
9156
9157         errlinno = lineno = n->ncase.linno;
9158         if (funcline)
9159                 lineno -= funcline - 1;
9160
9161         setstackmark(&smark);
9162         arglist.list = NULL;
9163         arglist.lastp = &arglist.list;
9164         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9165                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9166         }
9167         *arglist.lastp = NULL;
9168
9169         loopnest++;
9170         flags &= EV_TESTED;
9171         for (sp = arglist.list; sp; sp = sp->next) {
9172                 setvar0(n->nfor.var, sp->text);
9173                 status = evaltree(n->nfor.body, flags);
9174                 if (skiploop() & ~SKIPCONT)
9175                         break;
9176         }
9177         loopnest--;
9178         popstackmark(&smark);
9179
9180         return status;
9181 }
9182
9183 static int
9184 evalcase(union node *n, int flags)
9185 {
9186         union node *cp;
9187         union node *patp;
9188         struct arglist arglist;
9189         struct stackmark smark;
9190         int status = 0;
9191
9192         errlinno = lineno = n->ncase.linno;
9193         if (funcline)
9194                 lineno -= funcline - 1;
9195
9196         setstackmark(&smark);
9197         arglist.list = NULL;
9198         arglist.lastp = &arglist.list;
9199         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9200         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9201                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9202                         if (casematch(patp, arglist.list->text)) {
9203                                 /* Ensure body is non-empty as otherwise
9204                                  * EV_EXIT may prevent us from setting the
9205                                  * exit status.
9206                                  */
9207                                 if (evalskip == 0 && cp->nclist.body) {
9208                                         status = evaltree(cp->nclist.body, flags);
9209                                 }
9210                                 goto out;
9211                         }
9212                 }
9213         }
9214  out:
9215         popstackmark(&smark);
9216
9217         return status;
9218 }
9219
9220 /*
9221  * Kick off a subshell to evaluate a tree.
9222  */
9223 static int
9224 evalsubshell(union node *n, int flags)
9225 {
9226         struct job *jp;
9227         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9228         int status;
9229
9230         errlinno = lineno = n->nredir.linno;
9231         if (funcline)
9232                 lineno -= funcline - 1;
9233
9234         expredir(n->nredir.redirect);
9235         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9236                 goto nofork;
9237         INT_OFF;
9238         if (backgnd == FORK_FG)
9239                 get_tty_state();
9240         jp = makejob(/*n,*/ 1);
9241         if (forkshell(jp, n, backgnd) == 0) {
9242                 /* child */
9243                 INT_ON;
9244                 flags |= EV_EXIT;
9245                 if (backgnd)
9246                         flags &= ~EV_TESTED;
9247  nofork:
9248                 redirect(n->nredir.redirect, 0);
9249                 evaltreenr(n->nredir.n, flags);
9250                 /* never returns */
9251         }
9252         /* parent */
9253         status = 0;
9254         if (backgnd == FORK_FG)
9255                 status = waitforjob(jp);
9256         INT_ON;
9257         return status;
9258 }
9259
9260 /*
9261  * Compute the names of the files in a redirection list.
9262  */
9263 static void fixredir(union node *, const char *, int);
9264 static void
9265 expredir(union node *n)
9266 {
9267         union node *redir;
9268
9269         for (redir = n; redir; redir = redir->nfile.next) {
9270                 struct arglist fn;
9271
9272                 fn.list = NULL;
9273                 fn.lastp = &fn.list;
9274                 switch (redir->type) {
9275                 case NFROMTO:
9276                 case NFROM:
9277                 case NTO:
9278 #if BASH_REDIR_OUTPUT
9279                 case NTO2:
9280 #endif
9281                 case NCLOBBER:
9282                 case NAPPEND:
9283                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9284                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9285 #if BASH_REDIR_OUTPUT
9286  store_expfname:
9287 #endif
9288 #if 0
9289 // By the design of stack allocator, the loop of this kind:
9290 //      while true; do while true; do break; done </dev/null; done
9291 // will look like a memory leak: ash plans to free expfname's
9292 // of "/dev/null" as soon as it finishes running the loop
9293 // (in this case, never).
9294 // This "fix" is wrong:
9295                         if (redir->nfile.expfname)
9296                                 stunalloc(redir->nfile.expfname);
9297 // It results in corrupted state of stacked allocations.
9298 #endif
9299                         redir->nfile.expfname = fn.list->text;
9300                         break;
9301                 case NFROMFD:
9302                 case NTOFD: /* >& */
9303                         if (redir->ndup.vname) {
9304                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9305                                 if (fn.list == NULL)
9306                                         ash_msg_and_raise_error("redir error");
9307 #if BASH_REDIR_OUTPUT
9308 //FIXME: we used expandarg with different args!
9309                                 if (!isdigit_str9(fn.list->text)) {
9310                                         /* >&file, not >&fd */
9311                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9312                                                 ash_msg_and_raise_error("redir error");
9313                                         redir->type = NTO2;
9314                                         goto store_expfname;
9315                                 }
9316 #endif
9317                                 fixredir(redir, fn.list->text, 1);
9318                         }
9319                         break;
9320                 }
9321         }
9322 }
9323
9324 /*
9325  * Evaluate a pipeline.  All the processes in the pipeline are children
9326  * of the process creating the pipeline.  (This differs from some versions
9327  * of the shell, which make the last process in a pipeline the parent
9328  * of all the rest.)
9329  */
9330 static int
9331 evalpipe(union node *n, int flags)
9332 {
9333         struct job *jp;
9334         struct nodelist *lp;
9335         int pipelen;
9336         int prevfd;
9337         int pip[2];
9338         int status = 0;
9339
9340         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9341         pipelen = 0;
9342         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9343                 pipelen++;
9344         flags |= EV_EXIT;
9345         INT_OFF;
9346         if (n->npipe.pipe_backgnd == 0)
9347                 get_tty_state();
9348         jp = makejob(/*n,*/ pipelen);
9349         prevfd = -1;
9350         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9351                 prehash(lp->n);
9352                 pip[1] = -1;
9353                 if (lp->next) {
9354                         if (pipe(pip) < 0) {
9355                                 close(prevfd);
9356                                 ash_msg_and_raise_perror("can't create pipe");
9357                         }
9358                 }
9359                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9360                         /* child */
9361                         INT_ON;
9362                         if (pip[1] >= 0) {
9363                                 close(pip[0]);
9364                         }
9365                         if (prevfd > 0) {
9366                                 dup2(prevfd, 0);
9367                                 close(prevfd);
9368                         }
9369                         if (pip[1] > 1) {
9370                                 dup2(pip[1], 1);
9371                                 close(pip[1]);
9372                         }
9373                         evaltreenr(lp->n, flags);
9374                         /* never returns */
9375                 }
9376                 /* parent */
9377                 if (prevfd >= 0)
9378                         close(prevfd);
9379                 prevfd = pip[0];
9380                 /* Don't want to trigger debugging */
9381                 if (pip[1] != -1)
9382                         close(pip[1]);
9383         }
9384         if (n->npipe.pipe_backgnd == 0) {
9385                 status = waitforjob(jp);
9386                 TRACE(("evalpipe:  job done exit status %d\n", status));
9387         }
9388         INT_ON;
9389
9390         return status;
9391 }
9392
9393 /*
9394  * Controls whether the shell is interactive or not.
9395  */
9396 static void
9397 setinteractive(int on)
9398 {
9399         static smallint is_interactive;
9400
9401         if (++on == is_interactive)
9402                 return;
9403         is_interactive = on;
9404         setsignal(SIGINT);
9405         setsignal(SIGQUIT);
9406         setsignal(SIGTERM);
9407 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9408         if (is_interactive > 1) {
9409                 /* Looks like they want an interactive shell */
9410                 static smallint did_banner;
9411
9412                 if (!did_banner) {
9413                         /* note: ash and hush share this string */
9414                         out1fmt("\n\n%s %s\n"
9415                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9416                                 "\n",
9417                                 bb_banner,
9418                                 "built-in shell (ash)"
9419                         );
9420                         did_banner = 1;
9421                 }
9422         }
9423 #endif
9424 }
9425
9426 static void
9427 optschanged(void)
9428 {
9429 #if DEBUG
9430         opentrace();
9431 #endif
9432         setinteractive(iflag);
9433         setjobctl(mflag);
9434 #if ENABLE_FEATURE_EDITING_VI
9435         if (viflag)
9436                 line_input_state->flags |= VI_MODE;
9437         else
9438                 line_input_state->flags &= ~VI_MODE;
9439 #else
9440         viflag = 0; /* forcibly keep the option off */
9441 #endif
9442 }
9443
9444 struct localvar_list {
9445         struct localvar_list *next;
9446         struct localvar *lv;
9447 };
9448
9449 static struct localvar_list *localvar_stack;
9450
9451 /*
9452  * Called after a function returns.
9453  * Interrupts must be off.
9454  */
9455 static void
9456 poplocalvars(int keep)
9457 {
9458         struct localvar_list *ll;
9459         struct localvar *lvp, *next;
9460         struct var *vp;
9461
9462         INT_OFF;
9463         ll = localvar_stack;
9464         localvar_stack = ll->next;
9465
9466         next = ll->lv;
9467         free(ll);
9468
9469         while ((lvp = next) != NULL) {
9470                 next = lvp->next;
9471                 vp = lvp->vp;
9472                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9473                 if (keep) {
9474                         int bits = VSTRFIXED;
9475
9476                         if (lvp->flags != VUNSET) {
9477                                 if (vp->var_text == lvp->text)
9478                                         bits |= VTEXTFIXED;
9479                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9480                                         free((char*)lvp->text);
9481                         }
9482
9483                         vp->flags &= ~bits;
9484                         vp->flags |= (lvp->flags & bits);
9485
9486                         if ((vp->flags &
9487                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9488                                 unsetvar(vp->var_text);
9489                 } else if (vp == NULL) {        /* $- saved */
9490                         memcpy(optlist, lvp->text, sizeof(optlist));
9491                         free((char*)lvp->text);
9492                         optschanged();
9493                 } else if (lvp->flags == VUNSET) {
9494                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9495                         unsetvar(vp->var_text);
9496                 } else {
9497                         if (vp->var_func)
9498                                 vp->var_func(var_end(lvp->text));
9499                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9500                                 free((char*)vp->var_text);
9501                         vp->flags = lvp->flags;
9502                         vp->var_text = lvp->text;
9503                 }
9504                 free(lvp);
9505         }
9506         INT_ON;
9507 }
9508
9509 /*
9510  * Create a new localvar environment.
9511  */
9512 static struct localvar_list *
9513 pushlocalvars(void)
9514 {
9515         struct localvar_list *ll;
9516
9517         INT_OFF;
9518         ll = ckzalloc(sizeof(*ll));
9519         /*ll->lv = NULL; - zalloc did it */
9520         ll->next = localvar_stack;
9521         localvar_stack = ll;
9522         INT_ON;
9523
9524         return ll->next;
9525 }
9526
9527 static void
9528 unwindlocalvars(struct localvar_list *stop)
9529 {
9530         while (localvar_stack != stop)
9531                 poplocalvars(0);
9532 }
9533
9534 static int
9535 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9536 {
9537         volatile struct shparam saveparam;
9538         struct jmploc *volatile savehandler;
9539         struct jmploc jmploc;
9540         int e;
9541         int savefuncline;
9542
9543         saveparam = shellparam;
9544         savefuncline = funcline;
9545         savehandler = exception_handler;
9546         e = setjmp(jmploc.loc);
9547         if (e) {
9548                 goto funcdone;
9549         }
9550         INT_OFF;
9551         exception_handler = &jmploc;
9552         shellparam.malloced = 0;
9553         func->count++;
9554         funcline = func->n.ndefun.linno;
9555         INT_ON;
9556         shellparam.nparam = argc - 1;
9557         shellparam.p = argv + 1;
9558 #if ENABLE_ASH_GETOPTS
9559         shellparam.optind = 1;
9560         shellparam.optoff = -1;
9561 #endif
9562         pushlocalvars();
9563         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9564         poplocalvars(0);
9565  funcdone:
9566         INT_OFF;
9567         funcline = savefuncline;
9568         freefunc(func);
9569         freeparam(&shellparam);
9570         shellparam = saveparam;
9571         exception_handler = savehandler;
9572         INT_ON;
9573         evalskip &= ~SKIPFUNC;
9574         return e;
9575 }
9576
9577 /*
9578  * Make a variable a local variable.  When a variable is made local, it's
9579  * value and flags are saved in a localvar structure.  The saved values
9580  * will be restored when the shell function returns.  We handle the name
9581  * "-" as a special case: it makes changes to "set +-options" local
9582  * (options will be restored on return from the function).
9583  */
9584 static void
9585 mklocal(char *name)
9586 {
9587         struct localvar *lvp;
9588         struct var **vpp;
9589         struct var *vp;
9590         char *eq = strchr(name, '=');
9591
9592         INT_OFF;
9593         /* Cater for duplicate "local". Examples:
9594          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9595          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9596          */
9597         lvp = localvar_stack->lv;
9598         while (lvp) {
9599                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9600                         if (eq)
9601                                 setvareq(name, 0);
9602                         /* else:
9603                          * it's a duplicate "local VAR" declaration, do nothing
9604                          */
9605                         goto ret;
9606                 }
9607                 lvp = lvp->next;
9608         }
9609
9610         lvp = ckzalloc(sizeof(*lvp));
9611         if (LONE_DASH(name)) {
9612                 char *p;
9613                 p = ckmalloc(sizeof(optlist));
9614                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9615                 vp = NULL;
9616         } else {
9617                 vpp = hashvar(name);
9618                 vp = *findvar(vpp, name);
9619                 if (vp == NULL) {
9620                         /* variable did not exist yet */
9621                         if (eq)
9622                                 vp = setvareq(name, VSTRFIXED);
9623                         else
9624                                 vp = setvar(name, NULL, VSTRFIXED);
9625                         lvp->flags = VUNSET;
9626                 } else {
9627                         lvp->text = vp->var_text;
9628                         lvp->flags = vp->flags;
9629                         /* make sure neither "struct var" nor string gets freed
9630                          * during (un)setting:
9631                          */
9632                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9633                         if (eq)
9634                                 setvareq(name, 0);
9635                         else
9636                                 /* "local VAR" unsets VAR: */
9637                                 setvar0(name, NULL);
9638                 }
9639         }
9640         lvp->vp = vp;
9641         lvp->next = localvar_stack->lv;
9642         localvar_stack->lv = lvp;
9643  ret:
9644         INT_ON;
9645 }
9646
9647 /*
9648  * The "local" command.
9649  */
9650 static int FAST_FUNC
9651 localcmd(int argc UNUSED_PARAM, char **argv)
9652 {
9653         char *name;
9654
9655         if (!localvar_stack)
9656                 ash_msg_and_raise_error("not in a function");
9657
9658         argv = argptr;
9659         while ((name = *argv++) != NULL) {
9660                 mklocal(name);
9661         }
9662         return 0;
9663 }
9664
9665 static int FAST_FUNC
9666 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9667 {
9668         return 1;
9669 }
9670
9671 static int FAST_FUNC
9672 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9673 {
9674         return 0;
9675 }
9676
9677 static int FAST_FUNC
9678 execcmd(int argc UNUSED_PARAM, char **argv)
9679 {
9680         optionarg = NULL;
9681         while (nextopt("a:") != '\0')
9682                 /* nextopt() sets optionarg to "-a ARGV0" */;
9683
9684         argv = argptr;
9685         if (argv[0]) {
9686                 char *prog;
9687
9688                 iflag = 0;              /* exit on error */
9689                 mflag = 0;
9690                 optschanged();
9691                 /* We should set up signals for "exec CMD"
9692                  * the same way as for "CMD" without "exec".
9693                  * But optschanged->setinteractive->setsignal
9694                  * still thought we are a root shell. Therefore, for example,
9695                  * SIGQUIT is still set to IGN. Fix it:
9696                  */
9697                 shlvl++;
9698                 setsignal(SIGQUIT);
9699                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9700                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9701                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9702
9703                 prog = argv[0];
9704                 if (optionarg)
9705                         argv[0] = optionarg;
9706                 shellexec(prog, argv, pathval(), 0);
9707                 /* NOTREACHED */
9708         }
9709         return 0;
9710 }
9711
9712 /*
9713  * The return command.
9714  */
9715 static int FAST_FUNC
9716 returncmd(int argc UNUSED_PARAM, char **argv)
9717 {
9718         /*
9719          * If called outside a function, do what ksh does;
9720          * skip the rest of the file.
9721          */
9722         evalskip = SKIPFUNC;
9723         return argv[1] ? number(argv[1]) : exitstatus;
9724 }
9725
9726 /* Forward declarations for builtintab[] */
9727 static int breakcmd(int, char **) FAST_FUNC;
9728 static int dotcmd(int, char **) FAST_FUNC;
9729 static int evalcmd(int, char **, int) FAST_FUNC;
9730 static int exitcmd(int, char **) FAST_FUNC;
9731 static int exportcmd(int, char **) FAST_FUNC;
9732 #if ENABLE_ASH_GETOPTS
9733 static int getoptscmd(int, char **) FAST_FUNC;
9734 #endif
9735 #if ENABLE_ASH_HELP
9736 static int helpcmd(int, char **) FAST_FUNC;
9737 #endif
9738 #if MAX_HISTORY
9739 static int historycmd(int, char **) FAST_FUNC;
9740 #endif
9741 #if ENABLE_FEATURE_SH_MATH
9742 static int letcmd(int, char **) FAST_FUNC;
9743 #endif
9744 static int readcmd(int, char **) FAST_FUNC;
9745 static int setcmd(int, char **) FAST_FUNC;
9746 static int shiftcmd(int, char **) FAST_FUNC;
9747 static int timescmd(int, char **) FAST_FUNC;
9748 static int trapcmd(int, char **) FAST_FUNC;
9749 static int umaskcmd(int, char **) FAST_FUNC;
9750 static int unsetcmd(int, char **) FAST_FUNC;
9751 static int ulimitcmd(int, char **) FAST_FUNC;
9752
9753 #define BUILTIN_NOSPEC          "0"
9754 #define BUILTIN_SPECIAL         "1"
9755 #define BUILTIN_REGULAR         "2"
9756 #define BUILTIN_SPEC_REG        "3"
9757 #define BUILTIN_ASSIGN          "4"
9758 #define BUILTIN_SPEC_ASSG       "5"
9759 #define BUILTIN_REG_ASSG        "6"
9760 #define BUILTIN_SPEC_REG_ASSG   "7"
9761
9762 /* Stubs for calling non-FAST_FUNC's */
9763 #if ENABLE_ASH_ECHO
9764 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9765 #endif
9766 #if ENABLE_ASH_PRINTF
9767 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9768 #endif
9769 #if ENABLE_ASH_TEST || BASH_TEST2
9770 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9771 #endif
9772
9773 /* Keep these in proper order since it is searched via bsearch() */
9774 static const struct builtincmd builtintab[] = {
9775         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9776         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9777 #if ENABLE_ASH_TEST
9778         { BUILTIN_REGULAR       "["       , testcmd    },
9779 #endif
9780 #if BASH_TEST2
9781         { BUILTIN_REGULAR       "[["      , testcmd    },
9782 #endif
9783 #if ENABLE_ASH_ALIAS
9784         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9785 #endif
9786 #if JOBS
9787         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9788 #endif
9789         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9790         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9791         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9792 #if ENABLE_ASH_CMDCMD
9793         { BUILTIN_REGULAR       "command" , commandcmd },
9794 #endif
9795         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9796 #if ENABLE_ASH_ECHO
9797         { BUILTIN_REGULAR       "echo"    , echocmd    },
9798 #endif
9799         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9800         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9801         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9802         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9803         { BUILTIN_REGULAR       "false"   , falsecmd   },
9804 #if JOBS
9805         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9806 #endif
9807 #if ENABLE_ASH_GETOPTS
9808         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9809 #endif
9810         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9811 #if ENABLE_ASH_HELP
9812         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9813 #endif
9814 #if MAX_HISTORY
9815         { BUILTIN_NOSPEC        "history" , historycmd },
9816 #endif
9817 #if JOBS
9818         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9819         { BUILTIN_REGULAR       "kill"    , killcmd    },
9820 #endif
9821 #if ENABLE_FEATURE_SH_MATH
9822         { BUILTIN_NOSPEC        "let"     , letcmd     },
9823 #endif
9824         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9825 #if ENABLE_ASH_PRINTF
9826         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9827 #endif
9828         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9829         { BUILTIN_REGULAR       "read"    , readcmd    },
9830         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9831         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9832         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9833         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9834 #if BASH_SOURCE
9835         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9836 #endif
9837 #if ENABLE_ASH_TEST
9838         { BUILTIN_REGULAR       "test"    , testcmd    },
9839 #endif
9840         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9841         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9842         { BUILTIN_REGULAR       "true"    , truecmd    },
9843         { BUILTIN_NOSPEC        "type"    , typecmd    },
9844         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9845         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9846 #if ENABLE_ASH_ALIAS
9847         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9848 #endif
9849         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9850         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9851 };
9852
9853 /* Should match the above table! */
9854 #define COMMANDCMD (builtintab + \
9855         /* . : */       2 + \
9856         /* [ */         1 * ENABLE_ASH_TEST + \
9857         /* [[ */        1 * BASH_TEST2 + \
9858         /* alias */     1 * ENABLE_ASH_ALIAS + \
9859         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9860         /* break cd cddir  */   3)
9861 #define EVALCMD (COMMANDCMD + \
9862         /* command */   1 * ENABLE_ASH_CMDCMD + \
9863         /* continue */  1 + \
9864         /* echo */      1 * ENABLE_ASH_ECHO + \
9865         0)
9866 #define EXECCMD (EVALCMD + \
9867         /* eval */      1)
9868
9869 /*
9870  * Search the table of builtin commands.
9871  */
9872 static int
9873 pstrcmp1(const void *a, const void *b)
9874 {
9875         return strcmp((char*)a, *(char**)b + 1);
9876 }
9877 static struct builtincmd *
9878 find_builtin(const char *name)
9879 {
9880         struct builtincmd *bp;
9881
9882         bp = bsearch(
9883                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9884                 pstrcmp1
9885         );
9886         return bp;
9887 }
9888
9889 /*
9890  * Execute a simple command.
9891  */
9892 static int
9893 isassignment(const char *p)
9894 {
9895         const char *q = endofname(p);
9896         if (p == q)
9897                 return 0;
9898         return *q == '=';
9899 }
9900 static int FAST_FUNC
9901 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9902 {
9903         /* Preserve exitstatus of a previous possible redirection
9904          * as POSIX mandates */
9905         return back_exitstatus;
9906 }
9907 static int
9908 evalcommand(union node *cmd, int flags)
9909 {
9910         static const struct builtincmd null_bltin = {
9911                 "\0\0", bltincmd /* why three NULs? */
9912         };
9913         struct localvar_list *localvar_stop;
9914         struct redirtab *redir_stop;
9915         struct stackmark smark;
9916         union node *argp;
9917         struct arglist arglist;
9918         struct arglist varlist;
9919         char **argv;
9920         int argc;
9921         const struct strlist *sp;
9922         struct cmdentry cmdentry;
9923         struct job *jp;
9924         char *lastarg;
9925         const char *path;
9926         int spclbltin;
9927         int status;
9928         char **nargv;
9929         smallint cmd_is_exec;
9930
9931         errlinno = lineno = cmd->ncmd.linno;
9932         if (funcline)
9933                 lineno -= funcline - 1;
9934
9935         /* First expand the arguments. */
9936         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9937         setstackmark(&smark);
9938         localvar_stop = pushlocalvars();
9939         back_exitstatus = 0;
9940
9941         cmdentry.cmdtype = CMDBUILTIN;
9942         cmdentry.u.cmd = &null_bltin;
9943         varlist.lastp = &varlist.list;
9944         *varlist.lastp = NULL;
9945         arglist.lastp = &arglist.list;
9946         *arglist.lastp = NULL;
9947
9948         argc = 0;
9949         if (cmd->ncmd.args) {
9950                 struct builtincmd *bcmd;
9951                 smallint pseudovarflag;
9952
9953                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9954                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9955
9956                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9957                         struct strlist **spp;
9958
9959                         spp = arglist.lastp;
9960                         if (pseudovarflag && isassignment(argp->narg.text))
9961                                 expandarg(argp, &arglist, EXP_VARTILDE);
9962                         else
9963                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9964
9965                         for (sp = *spp; sp; sp = sp->next)
9966                                 argc++;
9967                 }
9968         }
9969
9970         /* Reserve one extra spot at the front for shellexec. */
9971         nargv = stalloc(sizeof(char *) * (argc + 2));
9972         argv = ++nargv;
9973         for (sp = arglist.list; sp; sp = sp->next) {
9974                 TRACE(("evalcommand arg: %s\n", sp->text));
9975                 *nargv++ = sp->text;
9976         }
9977         *nargv = NULL;
9978
9979         lastarg = NULL;
9980         if (iflag && funcline == 0 && argc > 0)
9981                 lastarg = nargv[-1];
9982
9983         expredir(cmd->ncmd.redirect);
9984         redir_stop = pushredir(cmd->ncmd.redirect);
9985         preverrout_fd = 2;
9986         if (BASH_XTRACEFD && xflag) {
9987                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9988                  * we do not emulate this. We only use its value.
9989                  */
9990                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9991                 if (xtracefd && is_number(xtracefd))
9992                         preverrout_fd = atoi(xtracefd);
9993
9994         }
9995         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9996
9997         path = vpath.var_text;
9998         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9999                 struct strlist **spp;
10000                 char *p;
10001
10002                 spp = varlist.lastp;
10003                 expandarg(argp, &varlist, EXP_VARTILDE);
10004
10005                 mklocal((*spp)->text);
10006
10007                 /*
10008                  * Modify the command lookup path, if a PATH= assignment
10009                  * is present
10010                  */
10011                 p = (*spp)->text;
10012                 if (varcmp(p, path) == 0)
10013                         path = p;
10014         }
10015
10016         /* Print the command if xflag is set. */
10017         if (xflag) {
10018                 const char *pfx = "";
10019
10020                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10021
10022                 sp = varlist.list;
10023                 while (sp) {
10024                         char *varval = sp->text;
10025                         char *eq = strchrnul(varval, '=');
10026                         if (*eq)
10027                                 eq++;
10028                         fdprintf(preverrout_fd, "%s%.*s%s",
10029                                 pfx,
10030                                 (int)(eq - varval), varval,
10031                                 maybe_single_quote(eq)
10032                         );
10033                         sp = sp->next;
10034                         pfx = " ";
10035                 }
10036
10037                 sp = arglist.list;
10038                 while (sp) {
10039                         fdprintf(preverrout_fd, "%s%s",
10040                                 pfx,
10041                                 /* always quote if matches reserved word: */
10042                                 findkwd(sp->text)
10043                                 ? single_quote(sp->text)
10044                                 : maybe_single_quote(sp->text)
10045                         );
10046                         sp = sp->next;
10047                         pfx = " ";
10048                 }
10049                 safe_write(preverrout_fd, "\n", 1);
10050         }
10051
10052         cmd_is_exec = 0;
10053         spclbltin = -1;
10054
10055         /* Now locate the command. */
10056         if (argc) {
10057                 int cmd_flag = DO_ERR;
10058 #if ENABLE_ASH_CMDCMD
10059                 const char *oldpath = path + 5;
10060 #endif
10061                 path += 5;
10062                 for (;;) {
10063                         find_command(argv[0], &cmdentry, cmd_flag, path);
10064                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10065                                 flush_stdout_stderr();
10066                                 status = 127;
10067                                 goto bail;
10068                         }
10069
10070                         /* implement bltin and command here */
10071                         if (cmdentry.cmdtype != CMDBUILTIN)
10072                                 break;
10073                         if (spclbltin < 0)
10074                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10075                         if (cmdentry.u.cmd == EXECCMD)
10076                                 cmd_is_exec = 1;
10077 #if ENABLE_ASH_CMDCMD
10078                         if (cmdentry.u.cmd == COMMANDCMD) {
10079                                 path = oldpath;
10080                                 nargv = parse_command_args(argv, &path);
10081                                 if (!nargv)
10082                                         break;
10083                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10084                                  * nargv => "PROG". path is updated if -p.
10085                                  */
10086                                 argc -= nargv - argv;
10087                                 argv = nargv;
10088                                 cmd_flag |= DO_NOFUNC;
10089                         } else
10090 #endif
10091                                 break;
10092                 }
10093         }
10094
10095         if (status) {
10096  bail:
10097                 exitstatus = status;
10098
10099                 /* We have a redirection error. */
10100                 if (spclbltin > 0)
10101                         raise_exception(EXERROR);
10102
10103                 goto out;
10104         }
10105
10106         /* Execute the command. */
10107         switch (cmdentry.cmdtype) {
10108         default: {
10109
10110 #if ENABLE_FEATURE_SH_STANDALONE \
10111  && ENABLE_FEATURE_SH_NOFORK \
10112  && NUM_APPLETS > 1
10113 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10114  *     around run_nofork_applet() call.
10115  * (2) Should this check also be done in forkshell()?
10116  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10117  */
10118                 /* find_command() encodes applet_no as (-2 - applet_no) */
10119                 int applet_no = (- cmdentry.u.index - 2);
10120                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10121                         char **sv_environ;
10122
10123                         INT_OFF;
10124                         sv_environ = environ;
10125                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10126                         /*
10127                          * Run <applet>_main().
10128                          * Signals (^C) can't interrupt here.
10129                          * Otherwise we can mangle stdio or malloc internal state.
10130                          * This makes applets which can run for a long time
10131                          * and/or wait for user input ineligible for NOFORK:
10132                          * for example, "yes" or "rm" (rm -i waits for input).
10133                          */
10134                         status = run_nofork_applet(applet_no, argv);
10135                         environ = sv_environ;
10136                         /*
10137                          * Try enabling NOFORK for "yes" applet.
10138                          * ^C _will_ stop it (write returns EINTR),
10139                          * but this causes stdout FILE to be stuck
10140                          * and needing clearerr(). What if other applets
10141                          * also can get EINTRs? Do we need to switch
10142                          * our signals to SA_RESTART?
10143                          */
10144                         /*clearerr(stdout);*/
10145                         INT_ON;
10146                         break;
10147                 }
10148 #endif
10149                 /* Can we avoid forking? For example, very last command
10150                  * in a script or a subshell does not need forking,
10151                  * we can just exec it.
10152                  */
10153                 if (!(flags & EV_EXIT) || may_have_traps) {
10154                         /* No, forking off a child is necessary */
10155                         INT_OFF;
10156                         get_tty_state();
10157                         jp = makejob(/*cmd,*/ 1);
10158                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10159                                 /* parent */
10160                                 status = waitforjob(jp);
10161                                 INT_ON;
10162                                 TRACE(("forked child exited with %d\n", status));
10163                                 break;
10164                         }
10165                         /* child */
10166                         FORCE_INT_ON;
10167                         /* fall through to exec'ing external program */
10168                 }
10169                 listsetvar(varlist.list, VEXPORT|VSTACK);
10170                 shellexec(argv[0], argv, path, cmdentry.u.index);
10171                 /* NOTREACHED */
10172         } /* default */
10173         case CMDBUILTIN:
10174                 if (spclbltin > 0 || argc == 0) {
10175                         poplocalvars(1);
10176                         if (cmd_is_exec && argc > 1)
10177                                 listsetvar(varlist.list, VEXPORT);
10178                 }
10179
10180                 /* Tight loop with builtins only:
10181                  * "while kill -0 $child; do true; done"
10182                  * will never exit even if $child died, unless we do this
10183                  * to reap the zombie and make kill detect that it's gone: */
10184                 dowait(DOWAIT_NONBLOCK, NULL);
10185
10186                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10187                         if (exception_type == EXERROR && spclbltin <= 0) {
10188                                 FORCE_INT_ON;
10189                                 goto readstatus;
10190                         }
10191  raise:
10192                         longjmp(exception_handler->loc, 1);
10193                 }
10194                 goto readstatus;
10195
10196         case CMDFUNCTION:
10197                 poplocalvars(1);
10198                 /* See above for the rationale */
10199                 dowait(DOWAIT_NONBLOCK, NULL);
10200                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10201                         goto raise;
10202  readstatus:
10203                 status = exitstatus;
10204                 break;
10205         } /* switch */
10206
10207  out:
10208         if (cmd->ncmd.redirect)
10209                 popredir(/*drop:*/ cmd_is_exec);
10210         unwindredir(redir_stop);
10211         unwindlocalvars(localvar_stop);
10212         if (lastarg) {
10213                 /* dsl: I think this is intended to be used to support
10214                  * '_' in 'vi' command mode during line editing...
10215                  * However I implemented that within libedit itself.
10216                  */
10217                 setvar0("_", lastarg);
10218         }
10219         popstackmark(&smark);
10220
10221         return status;
10222 }
10223
10224 static int
10225 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10226 {
10227         char *volatile savecmdname;
10228         struct jmploc *volatile savehandler;
10229         struct jmploc jmploc;
10230         int status;
10231         int i;
10232
10233         savecmdname = commandname;
10234         savehandler = exception_handler;
10235         i = setjmp(jmploc.loc);
10236         if (i)
10237                 goto cmddone;
10238         exception_handler = &jmploc;
10239         commandname = argv[0];
10240         argptr = argv + 1;
10241         optptr = NULL;                  /* initialize nextopt */
10242         if (cmd == EVALCMD)
10243                 status = evalcmd(argc, argv, flags);
10244         else
10245                 status = (*cmd->builtin)(argc, argv);
10246         flush_stdout_stderr();
10247         status |= ferror(stdout);
10248         exitstatus = status;
10249  cmddone:
10250         clearerr(stdout);
10251         commandname = savecmdname;
10252         exception_handler = savehandler;
10253
10254         return i;
10255 }
10256
10257 static int
10258 goodname(const char *p)
10259 {
10260         return endofname(p)[0] == '\0';
10261 }
10262
10263
10264 /*
10265  * Search for a command.  This is called before we fork so that the
10266  * location of the command will be available in the parent as well as
10267  * the child.  The check for "goodname" is an overly conservative
10268  * check that the name will not be subject to expansion.
10269  */
10270 static void
10271 prehash(union node *n)
10272 {
10273         struct cmdentry entry;
10274
10275         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10276                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10277 }
10278
10279
10280 /* ============ Builtin commands
10281  *
10282  * Builtin commands whose functions are closely tied to evaluation
10283  * are implemented here.
10284  */
10285
10286 /*
10287  * Handle break and continue commands.  Break, continue, and return are
10288  * all handled by setting the evalskip flag.  The evaluation routines
10289  * above all check this flag, and if it is set they start skipping
10290  * commands rather than executing them.  The variable skipcount is
10291  * the number of loops to break/continue, or the number of function
10292  * levels to return.  (The latter is always 1.)  It should probably
10293  * be an error to break out of more loops than exist, but it isn't
10294  * in the standard shell so we don't make it one here.
10295  */
10296 static int FAST_FUNC
10297 breakcmd(int argc UNUSED_PARAM, char **argv)
10298 {
10299         int n = argv[1] ? number(argv[1]) : 1;
10300
10301         if (n <= 0)
10302                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10303         if (n > loopnest)
10304                 n = loopnest;
10305         if (n > 0) {
10306                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10307                 skipcount = n;
10308         }
10309         return 0;
10310 }
10311
10312
10313 /*
10314  * This implements the input routines used by the parser.
10315  */
10316
10317 enum {
10318         INPUT_PUSH_FILE = 1,
10319         INPUT_NOFILE_OK = 2,
10320 };
10321
10322 static smallint checkkwd;
10323 /* values of checkkwd variable */
10324 #define CHKALIAS        0x1
10325 #define CHKKWD          0x2
10326 #define CHKNL           0x4
10327 #define CHKEOFMARK      0x8
10328
10329 /*
10330  * Push a string back onto the input at this current parsefile level.
10331  * We handle aliases this way.
10332  */
10333 #if !ENABLE_ASH_ALIAS
10334 #define pushstring(s, ap) pushstring(s)
10335 #endif
10336 static void
10337 pushstring(char *s, struct alias *ap)
10338 {
10339         struct strpush *sp;
10340         int len;
10341
10342         len = strlen(s);
10343         INT_OFF;
10344         if (g_parsefile->strpush) {
10345                 sp = ckzalloc(sizeof(*sp));
10346                 sp->prev = g_parsefile->strpush;
10347         } else {
10348                 sp = &(g_parsefile->basestrpush);
10349         }
10350         g_parsefile->strpush = sp;
10351         sp->prev_string = g_parsefile->next_to_pgetc;
10352         sp->prev_left_in_line = g_parsefile->left_in_line;
10353         sp->unget = g_parsefile->unget;
10354         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10355 #if ENABLE_ASH_ALIAS
10356         sp->ap = ap;
10357         if (ap) {
10358                 ap->flag |= ALIASINUSE;
10359                 sp->string = s;
10360         }
10361 #endif
10362         g_parsefile->next_to_pgetc = s;
10363         g_parsefile->left_in_line = len;
10364         g_parsefile->unget = 0;
10365         INT_ON;
10366 }
10367
10368 static void
10369 popstring(void)
10370 {
10371         struct strpush *sp = g_parsefile->strpush;
10372
10373         INT_OFF;
10374 #if ENABLE_ASH_ALIAS
10375         if (sp->ap) {
10376                 if (g_parsefile->next_to_pgetc[-1] == ' '
10377                  || g_parsefile->next_to_pgetc[-1] == '\t'
10378                 ) {
10379                         checkkwd |= CHKALIAS;
10380                 }
10381                 if (sp->string != sp->ap->val) {
10382                         free(sp->string);
10383                 }
10384                 sp->ap->flag &= ~ALIASINUSE;
10385                 if (sp->ap->flag & ALIASDEAD) {
10386                         unalias(sp->ap->name);
10387                 }
10388         }
10389 #endif
10390         g_parsefile->next_to_pgetc = sp->prev_string;
10391         g_parsefile->left_in_line = sp->prev_left_in_line;
10392         g_parsefile->unget = sp->unget;
10393         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10394         g_parsefile->strpush = sp->prev;
10395         if (sp != &(g_parsefile->basestrpush))
10396                 free(sp);
10397         INT_ON;
10398 }
10399
10400 static int
10401 preadfd(void)
10402 {
10403         int nr;
10404         char *buf = g_parsefile->buf;
10405
10406         g_parsefile->next_to_pgetc = buf;
10407 #if ENABLE_FEATURE_EDITING
10408  retry:
10409         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10410                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10411         else {
10412 # if ENABLE_ASH_IDLE_TIMEOUT
10413                 int timeout = -1;
10414                 if (iflag) {
10415                         const char *tmout_var = lookupvar("TMOUT");
10416                         if (tmout_var) {
10417                                 timeout = atoi(tmout_var) * 1000;
10418                                 if (timeout <= 0)
10419                                         timeout = -1;
10420                         }
10421                 }
10422                 line_input_state->timeout = timeout;
10423 # endif
10424 # if ENABLE_FEATURE_TAB_COMPLETION
10425                 line_input_state->path_lookup = pathval();
10426 # endif
10427                 reinit_unicode_for_ash();
10428                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10429                 if (nr == 0) {
10430                         /* ^C pressed, "convert" to SIGINT */
10431                         write(STDOUT_FILENO, "^C", 2);
10432                         if (trap[SIGINT]) {
10433                                 buf[0] = '\n';
10434                                 buf[1] = '\0';
10435                                 raise(SIGINT);
10436                                 return 1;
10437                         }
10438                         exitstatus = 128 + SIGINT;
10439                         bb_putchar('\n');
10440                         goto retry;
10441                 }
10442                 if (nr < 0) {
10443                         if (errno == 0) {
10444                                 /* Ctrl+D pressed */
10445                                 nr = 0;
10446                         }
10447 # if ENABLE_ASH_IDLE_TIMEOUT
10448                         else if (errno == EAGAIN && timeout > 0) {
10449                                 puts("\007timed out waiting for input: auto-logout");
10450                                 exitshell();
10451                         }
10452 # endif
10453                 }
10454         }
10455 #else
10456         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10457 #endif
10458
10459 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10460         if (nr < 0) {
10461                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10462                         int flags = fcntl(0, F_GETFL);
10463                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10464                                 flags &= ~O_NONBLOCK;
10465                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10466                                         out2str("sh: turning off NDELAY mode\n");
10467                                         goto retry;
10468                                 }
10469                         }
10470                 }
10471         }
10472 #endif
10473         return nr;
10474 }
10475
10476 /*
10477  * Refill the input buffer and return the next input character:
10478  *
10479  * 1) If a string was pushed back on the input, pop it;
10480  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10481  *    or we are reading from a string so we can't refill the buffer,
10482  *    return EOF.
10483  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10484  * 4) Process input up to the next newline, deleting nul characters.
10485  */
10486 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10487 #define pgetc_debug(...) ((void)0)
10488 static int pgetc(void);
10489 static int
10490 preadbuffer(void)
10491 {
10492         char *q;
10493         int more;
10494
10495         if (g_parsefile->strpush) {
10496 #if ENABLE_ASH_ALIAS
10497                 if (g_parsefile->left_in_line == -1
10498                  && g_parsefile->strpush->ap
10499                  && g_parsefile->next_to_pgetc[-1] != ' '
10500                  && g_parsefile->next_to_pgetc[-1] != '\t'
10501                 ) {
10502                         pgetc_debug("preadbuffer PEOA");
10503                         return PEOA;
10504                 }
10505 #endif
10506                 popstring();
10507                 return pgetc();
10508         }
10509         /* on both branches above g_parsefile->left_in_line < 0.
10510          * "pgetc" needs refilling.
10511          */
10512
10513         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10514          * pungetc() may increment it a few times.
10515          * Assuming it won't increment it to less than -90.
10516          */
10517         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10518                 pgetc_debug("preadbuffer PEOF1");
10519                 /* even in failure keep left_in_line and next_to_pgetc
10520                  * in lock step, for correct multi-layer pungetc.
10521                  * left_in_line was decremented before preadbuffer(),
10522                  * must inc next_to_pgetc: */
10523                 g_parsefile->next_to_pgetc++;
10524                 return PEOF;
10525         }
10526
10527         more = g_parsefile->left_in_buffer;
10528         if (more <= 0) {
10529                 flush_stdout_stderr();
10530  again:
10531                 more = preadfd();
10532                 if (more <= 0) {
10533                         /* don't try reading again */
10534                         g_parsefile->left_in_line = -99;
10535                         pgetc_debug("preadbuffer PEOF2");
10536                         g_parsefile->next_to_pgetc++;
10537                         return PEOF;
10538                 }
10539         }
10540
10541         /* Find out where's the end of line.
10542          * Set g_parsefile->left_in_line
10543          * and g_parsefile->left_in_buffer acordingly.
10544          * NUL chars are deleted.
10545          */
10546         q = g_parsefile->next_to_pgetc;
10547         for (;;) {
10548                 char c;
10549
10550                 more--;
10551
10552                 c = *q;
10553                 if (c == '\0') {
10554                         memmove(q, q + 1, more);
10555                 } else {
10556                         q++;
10557                         if (c == '\n') {
10558                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10559                                 break;
10560                         }
10561                 }
10562
10563                 if (more <= 0) {
10564                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10565                         if (g_parsefile->left_in_line < 0)
10566                                 goto again;
10567                         break;
10568                 }
10569         }
10570         g_parsefile->left_in_buffer = more;
10571
10572         if (vflag) {
10573                 char save = *q;
10574                 *q = '\0';
10575                 out2str(g_parsefile->next_to_pgetc);
10576                 *q = save;
10577         }
10578
10579         pgetc_debug("preadbuffer at %d:%p'%s'",
10580                         g_parsefile->left_in_line,
10581                         g_parsefile->next_to_pgetc,
10582                         g_parsefile->next_to_pgetc);
10583         return (unsigned char)*g_parsefile->next_to_pgetc++;
10584 }
10585
10586 static void
10587 nlprompt(void)
10588 {
10589         g_parsefile->linno++;
10590         setprompt_if(doprompt, 2);
10591 }
10592 static void
10593 nlnoprompt(void)
10594 {
10595         g_parsefile->linno++;
10596         needprompt = doprompt;
10597 }
10598
10599 static int
10600 pgetc(void)
10601 {
10602         int c;
10603
10604         pgetc_debug("pgetc at %d:%p'%s'",
10605                         g_parsefile->left_in_line,
10606                         g_parsefile->next_to_pgetc,
10607                         g_parsefile->next_to_pgetc);
10608         if (g_parsefile->unget)
10609                 return g_parsefile->lastc[--g_parsefile->unget];
10610
10611         if (--g_parsefile->left_in_line >= 0)
10612                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10613         else
10614                 c = preadbuffer();
10615
10616         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10617         g_parsefile->lastc[0] = c;
10618
10619         return c;
10620 }
10621
10622 #if ENABLE_ASH_ALIAS
10623 static int
10624 pgetc_without_PEOA(void)
10625 {
10626         int c;
10627         do {
10628                 pgetc_debug("pgetc at %d:%p'%s'",
10629                                 g_parsefile->left_in_line,
10630                                 g_parsefile->next_to_pgetc,
10631                                 g_parsefile->next_to_pgetc);
10632                 c = pgetc();
10633         } while (c == PEOA);
10634         return c;
10635 }
10636 #else
10637 # define pgetc_without_PEOA() pgetc()
10638 #endif
10639
10640 /*
10641  * Undo a call to pgetc.  Only two characters may be pushed back.
10642  * PEOF may be pushed back.
10643  */
10644 static void
10645 pungetc(void)
10646 {
10647         g_parsefile->unget++;
10648 }
10649
10650 /* This one eats backslash+newline */
10651 static int
10652 pgetc_eatbnl(void)
10653 {
10654         int c;
10655
10656         while ((c = pgetc()) == '\\') {
10657                 if (pgetc() != '\n') {
10658                         pungetc();
10659                         break;
10660                 }
10661
10662                 nlprompt();
10663         }
10664
10665         return c;
10666 }
10667
10668 struct synstack {
10669         smalluint syntax;
10670         uint8_t innerdq   :1;
10671         uint8_t varpushed :1;
10672         uint8_t dblquote  :1;
10673         int varnest;            /* levels of variables expansion */
10674         int dqvarnest;          /* levels of variables expansion within double quotes */
10675         int parenlevel;         /* levels of parens in arithmetic */
10676         struct synstack *prev;
10677         struct synstack *next;
10678 };
10679
10680 static void
10681 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10682 {
10683         memset(next, 0, sizeof(*next));
10684         next->syntax = syntax;
10685         next->next = *stack;
10686         (*stack)->prev = next;
10687         *stack = next;
10688 }
10689
10690 static ALWAYS_INLINE void
10691 synstack_pop(struct synstack **stack)
10692 {
10693         *stack = (*stack)->next;
10694 }
10695
10696 /*
10697  * To handle the "." command, a stack of input files is used.  Pushfile
10698  * adds a new entry to the stack and popfile restores the previous level.
10699  */
10700 static void
10701 pushfile(void)
10702 {
10703         struct parsefile *pf;
10704
10705         pf = ckzalloc(sizeof(*pf));
10706         pf->prev = g_parsefile;
10707         pf->pf_fd = -1;
10708         /*pf->strpush = NULL; - ckzalloc did it */
10709         /*pf->basestrpush.prev = NULL;*/
10710         /*pf->unget = 0;*/
10711         g_parsefile = pf;
10712 }
10713
10714 static void
10715 popfile(void)
10716 {
10717         struct parsefile *pf = g_parsefile;
10718
10719         if (pf == &basepf)
10720                 return;
10721
10722         INT_OFF;
10723         if (pf->pf_fd >= 0)
10724                 close(pf->pf_fd);
10725         free(pf->buf);
10726         while (pf->strpush)
10727                 popstring();
10728         g_parsefile = pf->prev;
10729         free(pf);
10730         INT_ON;
10731 }
10732
10733 /*
10734  * Return to top level.
10735  */
10736 static void
10737 popallfiles(void)
10738 {
10739         while (g_parsefile != &basepf)
10740                 popfile();
10741 }
10742
10743 /*
10744  * Close the file(s) that the shell is reading commands from.  Called
10745  * after a fork is done.
10746  */
10747 static void
10748 closescript(void)
10749 {
10750         popallfiles();
10751         if (g_parsefile->pf_fd > 0) {
10752                 close(g_parsefile->pf_fd);
10753                 g_parsefile->pf_fd = 0;
10754         }
10755 }
10756
10757 /*
10758  * Like setinputfile, but takes an open file descriptor.  Call this with
10759  * interrupts off.
10760  */
10761 static void
10762 setinputfd(int fd, int push)
10763 {
10764         if (push) {
10765                 pushfile();
10766                 g_parsefile->buf = NULL;
10767         }
10768         g_parsefile->pf_fd = fd;
10769         if (g_parsefile->buf == NULL)
10770                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10771         g_parsefile->left_in_buffer = 0;
10772         g_parsefile->left_in_line = 0;
10773         g_parsefile->linno = 1;
10774 }
10775
10776 /*
10777  * Set the input to take input from a file.  If push is set, push the
10778  * old input onto the stack first.
10779  */
10780 static int
10781 setinputfile(const char *fname, int flags)
10782 {
10783         int fd;
10784
10785         INT_OFF;
10786         fd = open(fname, O_RDONLY | O_CLOEXEC);
10787         if (fd < 0) {
10788                 if (flags & INPUT_NOFILE_OK)
10789                         goto out;
10790                 exitstatus = 127;
10791                 ash_msg_and_raise_perror("can't open '%s'", fname);
10792         }
10793         if (fd < 10)
10794                 fd = savefd(fd);
10795         else if (O_CLOEXEC == 0) /* old libc */
10796                 close_on_exec_on(fd);
10797
10798         setinputfd(fd, flags & INPUT_PUSH_FILE);
10799  out:
10800         INT_ON;
10801         return fd;
10802 }
10803
10804 /*
10805  * Like setinputfile, but takes input from a string.
10806  */
10807 static void
10808 setinputstring(char *string)
10809 {
10810         INT_OFF;
10811         pushfile();
10812         g_parsefile->next_to_pgetc = string;
10813         g_parsefile->left_in_line = strlen(string);
10814         g_parsefile->buf = NULL;
10815         g_parsefile->linno = 1;
10816         INT_ON;
10817 }
10818
10819
10820 /*
10821  * Routines to check for mail.
10822  */
10823
10824 #if ENABLE_ASH_MAIL
10825
10826 /* Hash of mtimes of mailboxes */
10827 static unsigned mailtime_hash;
10828 /* Set if MAIL or MAILPATH is changed. */
10829 static smallint mail_var_path_changed;
10830
10831 /*
10832  * Print appropriate message(s) if mail has arrived.
10833  * If mail_var_path_changed is set,
10834  * then the value of MAIL has mail_var_path_changed,
10835  * so we just update the values.
10836  */
10837 static void
10838 chkmail(void)
10839 {
10840         const char *mpath;
10841         char *p;
10842         char *q;
10843         unsigned new_hash;
10844         struct stackmark smark;
10845         struct stat statb;
10846
10847         setstackmark(&smark);
10848         mpath = mpathset() ? mpathval() : mailval();
10849         new_hash = 0;
10850         for (;;) {
10851                 p = path_advance(&mpath, nullstr);
10852                 if (p == NULL)
10853                         break;
10854                 if (*p == '\0')
10855                         continue;
10856                 for (q = p; *q; q++)
10857                         continue;
10858 #if DEBUG
10859                 if (q[-1] != '/')
10860                         abort();
10861 #endif
10862                 q[-1] = '\0';                   /* delete trailing '/' */
10863                 if (stat(p, &statb) < 0) {
10864                         continue;
10865                 }
10866                 /* Very simplistic "hash": just a sum of all mtimes */
10867                 new_hash += (unsigned)statb.st_mtime;
10868         }
10869         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10870                 if (mailtime_hash != 0)
10871                         out2str("you have mail\n");
10872                 mailtime_hash = new_hash;
10873         }
10874         mail_var_path_changed = 0;
10875         popstackmark(&smark);
10876 }
10877
10878 static void FAST_FUNC
10879 changemail(const char *val UNUSED_PARAM)
10880 {
10881         mail_var_path_changed = 1;
10882 }
10883
10884 #endif /* ASH_MAIL */
10885
10886
10887 /* ============ ??? */
10888
10889 /*
10890  * Set the shell parameters.
10891  */
10892 static void
10893 setparam(char **argv)
10894 {
10895         char **newparam;
10896         char **ap;
10897         int nparam;
10898
10899         for (nparam = 0; argv[nparam]; nparam++)
10900                 continue;
10901         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10902         while (*argv) {
10903                 *ap++ = ckstrdup(*argv++);
10904         }
10905         *ap = NULL;
10906         freeparam(&shellparam);
10907         shellparam.malloced = 1;
10908         shellparam.nparam = nparam;
10909         shellparam.p = newparam;
10910 #if ENABLE_ASH_GETOPTS
10911         shellparam.optind = 1;
10912         shellparam.optoff = -1;
10913 #endif
10914 }
10915
10916 /*
10917  * Process shell options.  The global variable argptr contains a pointer
10918  * to the argument list; we advance it past the options.
10919  *
10920  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10921  * For a non-interactive shell, an error condition encountered
10922  * by a special built-in ... shall cause the shell to write a diagnostic message
10923  * to standard error and exit as shown in the following table:
10924  * Error                                           Special Built-In
10925  * ...
10926  * Utility syntax error (option or operand error)  Shall exit
10927  * ...
10928  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10929  * we see that bash does not do that (set "finishes" with error code 1 instead,
10930  * and shell continues), and people rely on this behavior!
10931  * Testcase:
10932  * set -o barfoo 2>/dev/null
10933  * echo $?
10934  *
10935  * Oh well. Let's mimic that.
10936  */
10937 static int
10938 plus_minus_o(char *name, int val)
10939 {
10940         int i;
10941
10942         if (name) {
10943                 for (i = 0; i < NOPTS; i++) {
10944                         if (strcmp(name, optnames(i)) == 0) {
10945                                 optlist[i] = val;
10946                                 return 0;
10947                         }
10948                 }
10949                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10950                 return 1;
10951         }
10952         for (i = 0; i < NOPTS; i++) {
10953                 if (val) {
10954                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10955                 } else {
10956                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10957                 }
10958         }
10959         return 0;
10960 }
10961 static void
10962 setoption(int flag, int val)
10963 {
10964         int i;
10965
10966         for (i = 0; i < NOPTS; i++) {
10967                 if (optletters(i) == flag) {
10968                         optlist[i] = val;
10969                         return;
10970                 }
10971         }
10972         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10973         /* NOTREACHED */
10974 }
10975 static int
10976 options(int cmdline, int *login_sh)
10977 {
10978         char *p;
10979         int val;
10980         int c;
10981
10982         if (cmdline)
10983                 minusc = NULL;
10984         while ((p = *argptr) != NULL) {
10985                 c = *p++;
10986                 if (c != '-' && c != '+')
10987                         break;
10988                 argptr++;
10989                 val = 0; /* val = 0 if c == '+' */
10990                 if (c == '-') {
10991                         val = 1;
10992                         if (p[0] == '\0' || LONE_DASH(p)) {
10993                                 if (!cmdline) {
10994                                         /* "-" means turn off -x and -v */
10995                                         if (p[0] == '\0')
10996                                                 xflag = vflag = 0;
10997                                         /* "--" means reset params */
10998                                         else if (*argptr == NULL)
10999                                                 setparam(argptr);
11000                                 }
11001                                 break;    /* "-" or "--" terminates options */
11002                         }
11003                 }
11004                 /* first char was + or - */
11005                 while ((c = *p++) != '\0') {
11006                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11007                         if (c == 'c' && cmdline) {
11008                                 minusc = p;     /* command is after shell args */
11009                         } else if (c == 'o') {
11010                                 if (plus_minus_o(*argptr, val)) {
11011                                         /* it already printed err message */
11012                                         return 1; /* error */
11013                                 }
11014                                 if (*argptr)
11015                                         argptr++;
11016                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11017                                 if (login_sh)
11018                                         *login_sh = 1;
11019                         /* bash does not accept +-login, we also won't */
11020                         } else if (cmdline && val && (c == '-')) { /* long options */
11021                                 if (strcmp(p, "login") == 0) {
11022                                         if (login_sh)
11023                                                 *login_sh = 1;
11024                                 }
11025                                 break;
11026                         } else {
11027                                 setoption(c, val);
11028                         }
11029                 }
11030         }
11031         return 0;
11032 }
11033
11034 /*
11035  * The shift builtin command.
11036  */
11037 static int FAST_FUNC
11038 shiftcmd(int argc UNUSED_PARAM, char **argv)
11039 {
11040         int n;
11041         char **ap1, **ap2;
11042
11043         n = 1;
11044         if (argv[1])
11045                 n = number(argv[1]);
11046         if (n > shellparam.nparam)
11047                 return 1;
11048         INT_OFF;
11049         shellparam.nparam -= n;
11050         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11051                 if (shellparam.malloced)
11052                         free(*ap1);
11053         }
11054         ap2 = shellparam.p;
11055         while ((*ap2++ = *ap1++) != NULL)
11056                 continue;
11057 #if ENABLE_ASH_GETOPTS
11058         shellparam.optind = 1;
11059         shellparam.optoff = -1;
11060 #endif
11061         INT_ON;
11062         return 0;
11063 }
11064
11065 /*
11066  * POSIX requires that 'set' (but not export or readonly) output the
11067  * variables in lexicographic order - by the locale's collating order (sigh).
11068  * Maybe we could keep them in an ordered balanced binary tree
11069  * instead of hashed lists.
11070  * For now just roll 'em through qsort for printing...
11071  */
11072 static int
11073 showvars(const char *sep_prefix, int on, int off)
11074 {
11075         const char *sep;
11076         char **ep, **epend;
11077
11078         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11079         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11080
11081         sep = *sep_prefix ? " " : sep_prefix;
11082
11083         for (; ep < epend; ep++) {
11084                 const char *p;
11085                 const char *q;
11086
11087                 p = endofname(*ep);
11088 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11089  * makes "export -p" to have output not suitable for "eval":
11090  * import os
11091  * os.environ["test-test"]="test"
11092  * if os.fork() == 0:
11093  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11094  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11095  */
11096                 q = nullstr;
11097                 if (*p == '=')
11098                         q = single_quote(++p);
11099                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11100         }
11101         return 0;
11102 }
11103
11104 /*
11105  * The set command builtin.
11106  */
11107 static int FAST_FUNC
11108 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11109 {
11110         int retval;
11111
11112         if (!argv[1])
11113                 return showvars(nullstr, 0, VUNSET);
11114
11115         INT_OFF;
11116         retval = options(/*cmdline:*/ 0, NULL);
11117         if (retval == 0) { /* if no parse error... */
11118                 optschanged();
11119                 if (*argptr != NULL) {
11120                         setparam(argptr);
11121                 }
11122         }
11123         INT_ON;
11124         return retval;
11125 }
11126
11127 #if ENABLE_ASH_RANDOM_SUPPORT
11128 static void FAST_FUNC
11129 change_random(const char *value)
11130 {
11131         uint32_t t;
11132
11133         if (value == NULL) {
11134                 /* "get", generate */
11135                 t = next_random(&random_gen);
11136                 /* set without recursion */
11137                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11138                 vrandom.flags &= ~VNOFUNC;
11139         } else {
11140                 /* set/reset */
11141                 t = strtoul(value, NULL, 10);
11142                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11143         }
11144 }
11145 #endif
11146
11147 #if ENABLE_ASH_GETOPTS
11148 static int
11149 getopts(char *optstr, char *optvar, char **optfirst)
11150 {
11151         char *p, *q;
11152         char c = '?';
11153         int done = 0;
11154         char sbuf[2];
11155         char **optnext;
11156         int ind = shellparam.optind;
11157         int off = shellparam.optoff;
11158
11159         sbuf[1] = '\0';
11160
11161         shellparam.optind = -1;
11162         optnext = optfirst + ind - 1;
11163
11164         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11165                 p = NULL;
11166         else
11167                 p = optnext[-1] + off;
11168         if (p == NULL || *p == '\0') {
11169                 /* Current word is done, advance */
11170                 p = *optnext;
11171                 if (p == NULL || *p != '-' || *++p == '\0') {
11172  atend:
11173                         unsetvar("OPTARG");
11174                         p = NULL;
11175                         done = 1;
11176                         goto out;
11177                 }
11178                 optnext++;
11179                 if (LONE_DASH(p))        /* check for "--" */
11180                         goto atend;
11181         }
11182
11183         c = *p++;
11184         for (q = optstr; *q != c;) {
11185                 if (*q == '\0') {
11186                         /* OPTERR is a bashism */
11187                         const char *cp = lookupvar("OPTERR");
11188                         if ((cp && LONE_CHAR(cp, '0'))
11189                          || (optstr[0] == ':')
11190                         ) {
11191                                 sbuf[0] = c;
11192                                 /*sbuf[1] = '\0'; - already is */
11193                                 setvar0("OPTARG", sbuf);
11194                         } else {
11195                                 fprintf(stderr, "Illegal option -%c\n", c);
11196                                 unsetvar("OPTARG");
11197                         }
11198                         c = '?';
11199                         goto out;
11200                 }
11201                 if (*++q == ':')
11202                         q++;
11203         }
11204
11205         if (*++q == ':') {
11206                 if (*p == '\0' && (p = *optnext) == NULL) {
11207                         /* OPTERR is a bashism */
11208                         const char *cp = lookupvar("OPTERR");
11209                         if ((cp && LONE_CHAR(cp, '0'))
11210                          || (optstr[0] == ':')
11211                         ) {
11212                                 sbuf[0] = c;
11213                                 /*sbuf[1] = '\0'; - already is */
11214                                 setvar0("OPTARG", sbuf);
11215                                 c = ':';
11216                         } else {
11217                                 fprintf(stderr, "No arg for -%c option\n", c);
11218                                 unsetvar("OPTARG");
11219                                 c = '?';
11220                         }
11221                         goto out;
11222                 }
11223
11224                 if (p == *optnext)
11225                         optnext++;
11226                 setvar0("OPTARG", p);
11227                 p = NULL;
11228         } else
11229                 setvar0("OPTARG", nullstr);
11230  out:
11231         ind = optnext - optfirst + 1;
11232         setvar("OPTIND", itoa(ind), VNOFUNC);
11233         sbuf[0] = c;
11234         /*sbuf[1] = '\0'; - already is */
11235         setvar0(optvar, sbuf);
11236
11237         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11238         shellparam.optind = ind;
11239
11240         return done;
11241 }
11242
11243 /*
11244  * The getopts builtin.  Shellparam.optnext points to the next argument
11245  * to be processed.  Shellparam.optptr points to the next character to
11246  * be processed in the current argument.  If shellparam.optnext is NULL,
11247  * then it's the first time getopts has been called.
11248  */
11249 static int FAST_FUNC
11250 getoptscmd(int argc, char **argv)
11251 {
11252         char **optbase;
11253
11254         if (argc < 3)
11255                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11256         if (argc == 3) {
11257                 optbase = shellparam.p;
11258                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11259                         shellparam.optind = 1;
11260                         shellparam.optoff = -1;
11261                 }
11262         } else {
11263                 optbase = &argv[3];
11264                 if ((unsigned)shellparam.optind > argc - 2) {
11265                         shellparam.optind = 1;
11266                         shellparam.optoff = -1;
11267                 }
11268         }
11269
11270         return getopts(argv[1], argv[2], optbase);
11271 }
11272 #endif /* ASH_GETOPTS */
11273
11274
11275 /* ============ Shell parser */
11276
11277 struct heredoc {
11278         struct heredoc *next;   /* next here document in list */
11279         union node *here;       /* redirection node */
11280         char *eofmark;          /* string indicating end of input */
11281         smallint striptabs;     /* if set, strip leading tabs */
11282 };
11283
11284 static smallint tokpushback;           /* last token pushed back */
11285 static smallint quoteflag;             /* set if (part of) last token was quoted */
11286 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11287 static struct heredoc *heredoclist;    /* list of here documents to read */
11288 static char *wordtext;                 /* text of last word returned by readtoken */
11289 static struct nodelist *backquotelist;
11290 static union node *redirnode;
11291 static struct heredoc *heredoc;
11292
11293 static const char *
11294 tokname(char *buf, int tok)
11295 {
11296         if (tok < TSEMI)
11297                 return tokname_array[tok];
11298         sprintf(buf, "\"%s\"", tokname_array[tok]);
11299         return buf;
11300 }
11301
11302 /* raise_error_unexpected_syntax:
11303  * Called when an unexpected token is read during the parse.  The argument
11304  * is the token that is expected, or -1 if more than one type of token can
11305  * occur at this point.
11306  */
11307 static void raise_error_unexpected_syntax(int) NORETURN;
11308 static void
11309 raise_error_unexpected_syntax(int token)
11310 {
11311         char msg[64];
11312         char buf[16];
11313         int l;
11314
11315         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11316         if (token >= 0)
11317                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11318         raise_error_syntax(msg);
11319         /* NOTREACHED */
11320 }
11321
11322 /* parsing is heavily cross-recursive, need these forward decls */
11323 static union node *andor(void);
11324 static union node *pipeline(void);
11325 static union node *parse_command(void);
11326 static void parseheredoc(void);
11327 static int peektoken(void);
11328 static int readtoken(void);
11329
11330 static union node *
11331 list(int nlflag)
11332 {
11333         union node *n1, *n2, *n3;
11334         int tok;
11335
11336         n1 = NULL;
11337         for (;;) {
11338                 switch (peektoken()) {
11339                 case TNL:
11340                         if (!(nlflag & 1))
11341                                 break;
11342                         parseheredoc();
11343                         return n1;
11344
11345                 case TEOF:
11346                         if (!n1 && (nlflag & 1))
11347                                 n1 = NODE_EOF;
11348                         parseheredoc();
11349                         return n1;
11350                 }
11351
11352                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11353                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11354                         return n1;
11355                 nlflag |= 2;
11356
11357                 n2 = andor();
11358                 tok = readtoken();
11359                 if (tok == TBACKGND) {
11360                         if (n2->type == NPIPE) {
11361                                 n2->npipe.pipe_backgnd = 1;
11362                         } else {
11363                                 if (n2->type != NREDIR) {
11364                                         n3 = stzalloc(sizeof(struct nredir));
11365                                         n3->nredir.n = n2;
11366                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11367                                         n2 = n3;
11368                                 }
11369                                 n2->type = NBACKGND;
11370                         }
11371                 }
11372                 if (n1 == NULL) {
11373                         n1 = n2;
11374                 } else {
11375                         n3 = stzalloc(sizeof(struct nbinary));
11376                         n3->type = NSEMI;
11377                         n3->nbinary.ch1 = n1;
11378                         n3->nbinary.ch2 = n2;
11379                         n1 = n3;
11380                 }
11381                 switch (tok) {
11382                 case TNL:
11383                 case TEOF:
11384                         tokpushback = 1;
11385                         /* fall through */
11386                 case TBACKGND:
11387                 case TSEMI:
11388                         break;
11389                 default:
11390                         if ((nlflag & 1))
11391                                 raise_error_unexpected_syntax(-1);
11392                         tokpushback = 1;
11393                         return n1;
11394                 }
11395         }
11396 }
11397
11398 static union node *
11399 andor(void)
11400 {
11401         union node *n1, *n2, *n3;
11402         int t;
11403
11404         n1 = pipeline();
11405         for (;;) {
11406                 t = readtoken();
11407                 if (t == TAND) {
11408                         t = NAND;
11409                 } else if (t == TOR) {
11410                         t = NOR;
11411                 } else {
11412                         tokpushback = 1;
11413                         return n1;
11414                 }
11415                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11416                 n2 = pipeline();
11417                 n3 = stzalloc(sizeof(struct nbinary));
11418                 n3->type = t;
11419                 n3->nbinary.ch1 = n1;
11420                 n3->nbinary.ch2 = n2;
11421                 n1 = n3;
11422         }
11423 }
11424
11425 static union node *
11426 pipeline(void)
11427 {
11428         union node *n1, *n2, *pipenode;
11429         struct nodelist *lp, *prev;
11430         int negate;
11431
11432         negate = 0;
11433         TRACE(("pipeline: entered\n"));
11434         if (readtoken() == TNOT) {
11435                 negate = !negate;
11436                 checkkwd = CHKKWD | CHKALIAS;
11437         } else
11438                 tokpushback = 1;
11439         n1 = parse_command();
11440         if (readtoken() == TPIPE) {
11441                 pipenode = stzalloc(sizeof(struct npipe));
11442                 pipenode->type = NPIPE;
11443                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11444                 lp = stzalloc(sizeof(struct nodelist));
11445                 pipenode->npipe.cmdlist = lp;
11446                 lp->n = n1;
11447                 do {
11448                         prev = lp;
11449                         lp = stzalloc(sizeof(struct nodelist));
11450                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11451                         lp->n = parse_command();
11452                         prev->next = lp;
11453                 } while (readtoken() == TPIPE);
11454                 lp->next = NULL;
11455                 n1 = pipenode;
11456         }
11457         tokpushback = 1;
11458         if (negate) {
11459                 n2 = stzalloc(sizeof(struct nnot));
11460                 n2->type = NNOT;
11461                 n2->nnot.com = n1;
11462                 return n2;
11463         }
11464         return n1;
11465 }
11466
11467 static union node *
11468 makename(void)
11469 {
11470         union node *n;
11471
11472         n = stzalloc(sizeof(struct narg));
11473         n->type = NARG;
11474         /*n->narg.next = NULL; - stzalloc did it */
11475         n->narg.text = wordtext;
11476         n->narg.backquote = backquotelist;
11477         return n;
11478 }
11479
11480 static void
11481 fixredir(union node *n, const char *text, int err)
11482 {
11483         int fd;
11484
11485         TRACE(("Fix redir %s %d\n", text, err));
11486         if (!err)
11487                 n->ndup.vname = NULL;
11488
11489         fd = bb_strtou(text, NULL, 10);
11490         if (!errno && fd >= 0)
11491                 n->ndup.dupfd = fd;
11492         else if (LONE_DASH(text))
11493                 n->ndup.dupfd = -1;
11494         else {
11495                 if (err)
11496                         raise_error_syntax("bad fd number");
11497                 n->ndup.vname = makename();
11498         }
11499 }
11500
11501 static void
11502 parsefname(void)
11503 {
11504         union node *n = redirnode;
11505
11506         if (n->type == NHERE)
11507                 checkkwd = CHKEOFMARK;
11508         if (readtoken() != TWORD)
11509                 raise_error_unexpected_syntax(-1);
11510         if (n->type == NHERE) {
11511                 struct heredoc *here = heredoc;
11512                 struct heredoc *p;
11513
11514                 if (quoteflag == 0)
11515                         n->type = NXHERE;
11516                 TRACE(("Here document %d\n", n->type));
11517                 rmescapes(wordtext, 0, NULL);
11518                 here->eofmark = wordtext;
11519                 here->next = NULL;
11520                 if (heredoclist == NULL)
11521                         heredoclist = here;
11522                 else {
11523                         for (p = heredoclist; p->next; p = p->next)
11524                                 continue;
11525                         p->next = here;
11526                 }
11527         } else if (n->type == NTOFD || n->type == NFROMFD) {
11528                 fixredir(n, wordtext, 0);
11529         } else {
11530                 n->nfile.fname = makename();
11531         }
11532 }
11533
11534 static union node *
11535 simplecmd(void)
11536 {
11537         union node *args, **app;
11538         union node *n = NULL;
11539         union node *vars, **vpp;
11540         union node **rpp, *redir;
11541         int savecheckkwd;
11542         int savelinno;
11543 #if BASH_TEST2
11544         smallint double_brackets_flag = 0;
11545 #endif
11546         IF_BASH_FUNCTION(smallint function_flag = 0;)
11547
11548         args = NULL;
11549         app = &args;
11550         vars = NULL;
11551         vpp = &vars;
11552         redir = NULL;
11553         rpp = &redir;
11554
11555         savecheckkwd = CHKALIAS;
11556         savelinno = g_parsefile->linno;
11557         for (;;) {
11558                 int t;
11559                 checkkwd = savecheckkwd;
11560                 t = readtoken();
11561                 switch (t) {
11562 #if BASH_FUNCTION
11563                 case TFUNCTION:
11564                         if (peektoken() != TWORD)
11565                                 raise_error_unexpected_syntax(TWORD);
11566                         function_flag = 1;
11567                         break;
11568 #endif
11569 #if BASH_TEST2
11570                 case TAND: /* "&&" */
11571                 case TOR: /* "||" */
11572                         if (!double_brackets_flag) {
11573                                 tokpushback = 1;
11574                                 goto out;
11575                         }
11576                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11577 #endif
11578                 case TWORD:
11579                         n = stzalloc(sizeof(struct narg));
11580                         n->type = NARG;
11581                         /*n->narg.next = NULL; - stzalloc did it */
11582                         n->narg.text = wordtext;
11583 #if BASH_TEST2
11584                         if (strcmp("[[", wordtext) == 0)
11585                                 double_brackets_flag = 1;
11586                         else if (strcmp("]]", wordtext) == 0)
11587                                 double_brackets_flag = 0;
11588 #endif
11589                         n->narg.backquote = backquotelist;
11590                         if (savecheckkwd && isassignment(wordtext)) {
11591                                 *vpp = n;
11592                                 vpp = &n->narg.next;
11593                         } else {
11594                                 *app = n;
11595                                 app = &n->narg.next;
11596                                 savecheckkwd = 0;
11597                         }
11598 #if BASH_FUNCTION
11599                         if (function_flag) {
11600                                 checkkwd = CHKNL | CHKKWD;
11601                                 switch (peektoken()) {
11602                                 case TBEGIN:
11603                                 case TIF:
11604                                 case TCASE:
11605                                 case TUNTIL:
11606                                 case TWHILE:
11607                                 case TFOR:
11608                                         goto do_func;
11609                                 case TLP:
11610                                         function_flag = 0;
11611                                         break;
11612                                 case TWORD:
11613                                         if (strcmp("[[", wordtext) == 0)
11614                                                 goto do_func;
11615                                         /* fall through */
11616                                 default:
11617                                         raise_error_unexpected_syntax(-1);
11618                                 }
11619                         }
11620 #endif
11621                         break;
11622                 case TREDIR:
11623                         *rpp = n = redirnode;
11624                         rpp = &n->nfile.next;
11625                         parsefname();   /* read name of redirection file */
11626                         break;
11627                 case TLP:
11628  IF_BASH_FUNCTION(do_func:)
11629                         if (args && app == &args->narg.next
11630                          && !vars && !redir
11631                         ) {
11632                                 struct builtincmd *bcmd;
11633                                 const char *name;
11634
11635                                 /* We have a function */
11636                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11637                                         raise_error_unexpected_syntax(TRP);
11638                                 name = n->narg.text;
11639                                 if (!goodname(name)
11640                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11641                                 ) {
11642                                         raise_error_syntax("bad function name");
11643                                 }
11644                                 n->type = NDEFUN;
11645                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11646                                 n->ndefun.text = n->narg.text;
11647                                 n->ndefun.linno = g_parsefile->linno;
11648                                 n->ndefun.body = parse_command();
11649                                 return n;
11650                         }
11651                         IF_BASH_FUNCTION(function_flag = 0;)
11652                         /* fall through */
11653                 default:
11654                         tokpushback = 1;
11655                         goto out;
11656                 }
11657         }
11658  out:
11659         *app = NULL;
11660         *vpp = NULL;
11661         *rpp = NULL;
11662         n = stzalloc(sizeof(struct ncmd));
11663         n->type = NCMD;
11664         n->ncmd.linno = savelinno;
11665         n->ncmd.args = args;
11666         n->ncmd.assign = vars;
11667         n->ncmd.redirect = redir;
11668         return n;
11669 }
11670
11671 static union node *
11672 parse_command(void)
11673 {
11674         union node *n1, *n2;
11675         union node *ap, **app;
11676         union node *cp, **cpp;
11677         union node *redir, **rpp;
11678         union node **rpp2;
11679         int t;
11680         int savelinno;
11681
11682         redir = NULL;
11683         rpp2 = &redir;
11684
11685         savelinno = g_parsefile->linno;
11686
11687         switch (readtoken()) {
11688         default:
11689                 raise_error_unexpected_syntax(-1);
11690                 /* NOTREACHED */
11691         case TIF:
11692                 n1 = stzalloc(sizeof(struct nif));
11693                 n1->type = NIF;
11694                 n1->nif.test = list(0);
11695                 if (readtoken() != TTHEN)
11696                         raise_error_unexpected_syntax(TTHEN);
11697                 n1->nif.ifpart = list(0);
11698                 n2 = n1;
11699                 while (readtoken() == TELIF) {
11700                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11701                         n2 = n2->nif.elsepart;
11702                         n2->type = NIF;
11703                         n2->nif.test = list(0);
11704                         if (readtoken() != TTHEN)
11705                                 raise_error_unexpected_syntax(TTHEN);
11706                         n2->nif.ifpart = list(0);
11707                 }
11708                 if (lasttoken == TELSE)
11709                         n2->nif.elsepart = list(0);
11710                 else {
11711                         n2->nif.elsepart = NULL;
11712                         tokpushback = 1;
11713                 }
11714                 t = TFI;
11715                 break;
11716         case TWHILE:
11717         case TUNTIL: {
11718                 int got;
11719                 n1 = stzalloc(sizeof(struct nbinary));
11720                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11721                 n1->nbinary.ch1 = list(0);
11722                 got = readtoken();
11723                 if (got != TDO) {
11724                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11725                                         got == TWORD ? wordtext : ""));
11726                         raise_error_unexpected_syntax(TDO);
11727                 }
11728                 n1->nbinary.ch2 = list(0);
11729                 t = TDONE;
11730                 break;
11731         }
11732         case TFOR:
11733                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11734                         raise_error_syntax("bad for loop variable");
11735                 n1 = stzalloc(sizeof(struct nfor));
11736                 n1->type = NFOR;
11737                 n1->nfor.linno = savelinno;
11738                 n1->nfor.var = wordtext;
11739                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11740                 if (readtoken() == TIN) {
11741                         app = &ap;
11742                         while (readtoken() == TWORD) {
11743                                 n2 = stzalloc(sizeof(struct narg));
11744                                 n2->type = NARG;
11745                                 /*n2->narg.next = NULL; - stzalloc did it */
11746                                 n2->narg.text = wordtext;
11747                                 n2->narg.backquote = backquotelist;
11748                                 *app = n2;
11749                                 app = &n2->narg.next;
11750                         }
11751                         *app = NULL;
11752                         n1->nfor.args = ap;
11753                         if (lasttoken != TNL && lasttoken != TSEMI)
11754                                 raise_error_unexpected_syntax(-1);
11755                 } else {
11756                         n2 = stzalloc(sizeof(struct narg));
11757                         n2->type = NARG;
11758                         /*n2->narg.next = NULL; - stzalloc did it */
11759                         n2->narg.text = (char *)dolatstr;
11760                         /*n2->narg.backquote = NULL;*/
11761                         n1->nfor.args = n2;
11762                         /*
11763                          * Newline or semicolon here is optional (but note
11764                          * that the original Bourne shell only allowed NL).
11765                          */
11766                         if (lasttoken != TSEMI)
11767                                 tokpushback = 1;
11768                 }
11769                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11770                 if (readtoken() != TDO)
11771                         raise_error_unexpected_syntax(TDO);
11772                 n1->nfor.body = list(0);
11773                 t = TDONE;
11774                 break;
11775         case TCASE:
11776                 n1 = stzalloc(sizeof(struct ncase));
11777                 n1->type = NCASE;
11778                 n1->ncase.linno = savelinno;
11779                 if (readtoken() != TWORD)
11780                         raise_error_unexpected_syntax(TWORD);
11781                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11782                 n2->type = NARG;
11783                 /*n2->narg.next = NULL; - stzalloc did it */
11784                 n2->narg.text = wordtext;
11785                 n2->narg.backquote = backquotelist;
11786                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11787                 if (readtoken() != TIN)
11788                         raise_error_unexpected_syntax(TIN);
11789                 cpp = &n1->ncase.cases;
11790  next_case:
11791                 checkkwd = CHKNL | CHKKWD;
11792                 t = readtoken();
11793                 while (t != TESAC) {
11794                         if (lasttoken == TLP)
11795                                 readtoken();
11796                         *cpp = cp = stzalloc(sizeof(struct nclist));
11797                         cp->type = NCLIST;
11798                         app = &cp->nclist.pattern;
11799                         for (;;) {
11800                                 *app = ap = stzalloc(sizeof(struct narg));
11801                                 ap->type = NARG;
11802                                 /*ap->narg.next = NULL; - stzalloc did it */
11803                                 ap->narg.text = wordtext;
11804                                 ap->narg.backquote = backquotelist;
11805                                 if (readtoken() != TPIPE)
11806                                         break;
11807                                 app = &ap->narg.next;
11808                                 readtoken();
11809                         }
11810                         //ap->narg.next = NULL;
11811                         if (lasttoken != TRP)
11812                                 raise_error_unexpected_syntax(TRP);
11813                         cp->nclist.body = list(2);
11814
11815                         cpp = &cp->nclist.next;
11816
11817                         checkkwd = CHKNL | CHKKWD;
11818                         t = readtoken();
11819                         if (t != TESAC) {
11820                                 if (t != TENDCASE)
11821                                         raise_error_unexpected_syntax(TENDCASE);
11822                                 goto next_case;
11823                         }
11824                 }
11825                 *cpp = NULL;
11826                 goto redir;
11827         case TLP:
11828                 n1 = stzalloc(sizeof(struct nredir));
11829                 n1->type = NSUBSHELL;
11830                 n1->nredir.linno = savelinno;
11831                 n1->nredir.n = list(0);
11832                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11833                 t = TRP;
11834                 break;
11835         case TBEGIN:
11836                 n1 = list(0);
11837                 t = TEND;
11838                 break;
11839         IF_BASH_FUNCTION(case TFUNCTION:)
11840         case TWORD:
11841         case TREDIR:
11842                 tokpushback = 1;
11843                 return simplecmd();
11844         }
11845
11846         if (readtoken() != t)
11847                 raise_error_unexpected_syntax(t);
11848
11849  redir:
11850         /* Now check for redirection which may follow command */
11851         checkkwd = CHKKWD | CHKALIAS;
11852         rpp = rpp2;
11853         while (readtoken() == TREDIR) {
11854                 *rpp = n2 = redirnode;
11855                 rpp = &n2->nfile.next;
11856                 parsefname();
11857         }
11858         tokpushback = 1;
11859         *rpp = NULL;
11860         if (redir) {
11861                 if (n1->type != NSUBSHELL) {
11862                         n2 = stzalloc(sizeof(struct nredir));
11863                         n2->type = NREDIR;
11864                         n2->nredir.linno = savelinno;
11865                         n2->nredir.n = n1;
11866                         n1 = n2;
11867                 }
11868                 n1->nredir.redirect = redir;
11869         }
11870         return n1;
11871 }
11872
11873 #if BASH_DOLLAR_SQUOTE
11874 static int
11875 decode_dollar_squote(void)
11876 {
11877         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11878         int c, cnt;
11879         char *p;
11880         char buf[4];
11881
11882         c = pgetc();
11883         p = strchr(C_escapes, c);
11884         if (p) {
11885                 buf[0] = c;
11886                 p = buf;
11887                 cnt = 3;
11888                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11889                         do {
11890                                 c = pgetc();
11891                                 *++p = c;
11892                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11893                         pungetc();
11894                 } else if (c == 'x') { /* \xHH */
11895                         do {
11896                                 c = pgetc();
11897                                 *++p = c;
11898                         } while (isxdigit(c) && --cnt);
11899                         pungetc();
11900                         if (cnt == 3) { /* \x but next char is "bad" */
11901                                 c = 'x';
11902                                 goto unrecognized;
11903                         }
11904                 } else { /* simple seq like \\ or \t */
11905                         p++;
11906                 }
11907                 *p = '\0';
11908                 p = buf;
11909                 c = bb_process_escape_sequence((void*)&p);
11910         } else { /* unrecognized "\z": print both chars unless ' or " */
11911                 if (c != '\'' && c != '"') {
11912  unrecognized:
11913                         c |= 0x100; /* "please encode \, then me" */
11914                 }
11915         }
11916         return c;
11917 }
11918 #endif
11919
11920 /* Used by expandstr to get here-doc like behaviour. */
11921 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11922
11923 static ALWAYS_INLINE int
11924 realeofmark(const char *eofmark)
11925 {
11926         return eofmark && eofmark != FAKEEOFMARK;
11927 }
11928
11929 /*
11930  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11931  * is not NULL, read a here document.  In the latter case, eofmark is the
11932  * word which marks the end of the document and striptabs is true if
11933  * leading tabs should be stripped from the document.  The argument c
11934  * is the first character of the input token or document.
11935  *
11936  * Because C does not have internal subroutines, I have simulated them
11937  * using goto's to implement the subroutine linkage.  The following macros
11938  * will run code that appears at the end of readtoken1.
11939  */
11940 #define CHECKEND()      {goto checkend; checkend_return:;}
11941 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11942 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11943 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11944 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11945 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11946 static int
11947 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11948 {
11949         /* NB: syntax parameter fits into smallint */
11950         /* c parameter is an unsigned char or PEOF or PEOA */
11951         char *out;
11952         size_t len;
11953         struct nodelist *bqlist;
11954         smallint quotef;
11955         smallint oldstyle;
11956         smallint pssyntax;   /* we are expanding a prompt string */
11957         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11958         /* syntax stack */
11959         struct synstack synbase = { .syntax = syntax };
11960         struct synstack *synstack = &synbase;
11961
11962 #if ENABLE_ASH_EXPAND_PRMT
11963         pssyntax = (syntax == PSSYNTAX);
11964         if (pssyntax)
11965                 syntax = DQSYNTAX;
11966 #else
11967         pssyntax = 0; /* constant */
11968 #endif
11969         if (syntax == DQSYNTAX)
11970                 synstack->dblquote = 1;
11971         quotef = 0;
11972         bqlist = NULL;
11973
11974         STARTSTACKSTR(out);
11975  loop:
11976         /* For each line, until end of word */
11977         CHECKEND();     /* set c to PEOF if at end of here document */
11978         for (;;) {      /* until end of line or end of word */
11979                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11980                 switch (SIT(c, synstack->syntax)) {
11981                 case CNL:       /* '\n' */
11982                         if (synstack->syntax == BASESYNTAX)
11983                                 goto endword;   /* exit outer loop */
11984                         USTPUTC(c, out);
11985                         nlprompt();
11986                         c = pgetc();
11987                         goto loop;              /* continue outer loop */
11988                 case CWORD:
11989                         USTPUTC(c, out);
11990                         break;
11991                 case CCTL:
11992 #if BASH_DOLLAR_SQUOTE
11993                         if (c == '\\' && bash_dollar_squote) {
11994                                 c = decode_dollar_squote();
11995                                 if (c == '\0') {
11996                                         /* skip $'\000', $'\x00' (like bash) */
11997                                         break;
11998                                 }
11999                                 if (c & 0x100) {
12000                                         /* Unknown escape. Encode as '\z' */
12001                                         c = (unsigned char)c;
12002                                         if (eofmark == NULL || synstack->dblquote)
12003                                                 USTPUTC(CTLESC, out);
12004                                         USTPUTC('\\', out);
12005                                 }
12006                         }
12007 #endif
12008                         if (!eofmark || synstack->dblquote || synstack->varnest)
12009                                 USTPUTC(CTLESC, out);
12010                         USTPUTC(c, out);
12011                         break;
12012                 case CBACK:     /* backslash */
12013                         c = pgetc_without_PEOA();
12014                         if (c == PEOF) {
12015                                 USTPUTC(CTLESC, out);
12016                                 USTPUTC('\\', out);
12017                                 pungetc();
12018                         } else if (c == '\n') {
12019                                 nlprompt();
12020                         } else {
12021                                 if (pssyntax && c == '$') {
12022                                         USTPUTC(CTLESC, out);
12023                                         USTPUTC('\\', out);
12024                                 }
12025                                 /* Backslash is retained if we are in "str"
12026                                  * and next char isn't dquote-special.
12027                                  */
12028                                 if (synstack->dblquote
12029                                  && c != '\\'
12030                                  && c != '`'
12031                                  && c != '$'
12032                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12033                                  && (c != '}' || !synstack->varnest)
12034                                 ) {
12035                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12036                                         USTPUTC('\\', out);
12037                                 }
12038                                 USTPUTC(CTLESC, out);
12039                                 USTPUTC(c, out);
12040                                 quotef = 1;
12041                         }
12042                         break;
12043                 case CSQUOTE:
12044                         synstack->syntax = SQSYNTAX;
12045  quotemark:
12046                         if (eofmark == NULL) {
12047                                 USTPUTC(CTLQUOTEMARK, out);
12048                         }
12049                         break;
12050                 case CDQUOTE:
12051                         synstack->syntax = DQSYNTAX;
12052                         synstack->dblquote = 1;
12053  toggledq:
12054                         if (synstack->varnest)
12055                                 synstack->innerdq ^= 1;
12056                         goto quotemark;
12057                 case CENDQUOTE:
12058                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12059                         if (eofmark != NULL && synstack->varnest == 0) {
12060                                 USTPUTC(c, out);
12061                                 break;
12062                         }
12063
12064                         if (synstack->dqvarnest == 0) {
12065                                 synstack->syntax = BASESYNTAX;
12066                                 synstack->dblquote = 0;
12067                         }
12068
12069                         quotef = 1;
12070
12071                         if (c == '"')
12072                                 goto toggledq;
12073
12074                         goto quotemark;
12075                 case CVAR:      /* '$' */
12076                         PARSESUB();             /* parse substitution */
12077                         break;
12078                 case CENDVAR:   /* '}' */
12079                         if (!synstack->innerdq && synstack->varnest > 0) {
12080                                 if (!--synstack->varnest && synstack->varpushed)
12081                                         synstack_pop(&synstack);
12082                                 else if (synstack->dqvarnest > 0)
12083                                         synstack->dqvarnest--;
12084                                 c = CTLENDVAR;
12085                         }
12086                         USTPUTC(c, out);
12087                         break;
12088 #if ENABLE_FEATURE_SH_MATH
12089                 case CLP:       /* '(' in arithmetic */
12090                         synstack->parenlevel++;
12091                         USTPUTC(c, out);
12092                         break;
12093                 case CRP:       /* ')' in arithmetic */
12094                         if (synstack->parenlevel > 0) {
12095                                 synstack->parenlevel--;
12096                         } else {
12097                                 if (pgetc_eatbnl() == ')') {
12098                                         c = CTLENDARI;
12099                                         synstack_pop(&synstack);
12100                                 } else {
12101                                         /*
12102                                          * unbalanced parens
12103                                          * (don't 2nd guess - no error)
12104                                          */
12105                                         pungetc();
12106                                 }
12107                         }
12108                         USTPUTC(c, out);
12109                         break;
12110 #endif
12111                 case CBQUOTE:   /* '`' */
12112                         if (checkkwd & CHKEOFMARK) {
12113                                 quotef = 1;
12114                                 USTPUTC('`', out);
12115                                 break;
12116                         }
12117
12118                         PARSEBACKQOLD();
12119                         break;
12120                 case CENDFILE:
12121                         goto endword;           /* exit outer loop */
12122                 case CIGN:
12123                         break;
12124                 default:
12125                         if (synstack->varnest == 0) {
12126 #if BASH_REDIR_OUTPUT
12127                                 if (c == '&') {
12128 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12129                                         if (pgetc() == '>')
12130                                                 c = 0x100 + '>'; /* flag &> */
12131                                         pungetc();
12132                                 }
12133 #endif
12134                                 goto endword;   /* exit outer loop */
12135                         }
12136                         IF_ASH_ALIAS(if (c != PEOA))
12137                                 USTPUTC(c, out);
12138                 }
12139                 c = pgetc();
12140         } /* for (;;) */
12141  endword:
12142
12143 #if ENABLE_FEATURE_SH_MATH
12144         if (synstack->syntax == ARISYNTAX)
12145                 raise_error_syntax("missing '))'");
12146 #endif
12147         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12148                 raise_error_syntax("unterminated quoted string");
12149         if (synstack->varnest != 0) {
12150                 /* { */
12151                 raise_error_syntax("missing '}'");
12152         }
12153         USTPUTC('\0', out);
12154         len = out - (char *)stackblock();
12155         out = stackblock();
12156         if (eofmark == NULL) {
12157                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12158                  && quotef == 0
12159                 ) {
12160                         if (isdigit_str9(out)) {
12161                                 PARSEREDIR(); /* passed as params: out, c */
12162                                 lasttoken = TREDIR;
12163                                 return lasttoken;
12164                         }
12165                         /* else: non-number X seen, interpret it
12166                          * as "NNNX>file" = "NNNX >file" */
12167                 }
12168                 pungetc();
12169         }
12170         quoteflag = quotef;
12171         backquotelist = bqlist;
12172         grabstackblock(len);
12173         wordtext = out;
12174         lasttoken = TWORD;
12175         return lasttoken;
12176 /* end of readtoken routine */
12177
12178 /*
12179  * Check to see whether we are at the end of the here document.  When this
12180  * is called, c is set to the first character of the next input line.  If
12181  * we are at the end of the here document, this routine sets the c to PEOF.
12182  */
12183 checkend: {
12184         if (realeofmark(eofmark)) {
12185                 int markloc;
12186                 char *p;
12187
12188 #if ENABLE_ASH_ALIAS
12189                 if (c == PEOA)
12190                         c = pgetc_without_PEOA();
12191 #endif
12192                 if (striptabs) {
12193                         while (c == '\t') {
12194                                 c = pgetc_without_PEOA();
12195                         }
12196                 }
12197
12198                 markloc = out - (char *)stackblock();
12199                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12200                         if (c != *p)
12201                                 goto more_heredoc;
12202
12203                         c = pgetc_without_PEOA();
12204                 }
12205
12206                 if (c == '\n' || c == PEOF) {
12207                         c = PEOF;
12208                         g_parsefile->linno++;
12209                         needprompt = doprompt;
12210                 } else {
12211                         int len_here;
12212
12213  more_heredoc:
12214                         p = (char *)stackblock() + markloc + 1;
12215                         len_here = out - p;
12216
12217                         if (len_here) {
12218                                 len_here -= (c >= PEOF);
12219                                 c = p[-1];
12220
12221                                 if (len_here) {
12222                                         char *str;
12223
12224                                         str = alloca(len_here + 1);
12225                                         *(char *)mempcpy(str, p, len_here) = '\0';
12226
12227                                         pushstring(str, NULL);
12228                                 }
12229                         }
12230                 }
12231
12232                 STADJUST((char *)stackblock() + markloc - out, out);
12233         }
12234         goto checkend_return;
12235 }
12236
12237 /*
12238  * Parse a redirection operator.  The variable "out" points to a string
12239  * specifying the fd to be redirected.  The variable "c" contains the
12240  * first character of the redirection operator.
12241  */
12242 parseredir: {
12243         /* out is already checked to be a valid number or "" */
12244         int fd = (*out == '\0' ? -1 : atoi(out));
12245         union node *np;
12246
12247         np = stzalloc(sizeof(struct nfile));
12248         if (c == '>') {
12249                 np->nfile.fd = 1;
12250                 c = pgetc_eatbnl();
12251                 if (c == '>')
12252                         np->type = NAPPEND;
12253                 else if (c == '|')
12254                         np->type = NCLOBBER;
12255                 else if (c == '&')
12256                         np->type = NTOFD;
12257                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12258                 else {
12259                         np->type = NTO;
12260                         pungetc();
12261                 }
12262         }
12263 #if BASH_REDIR_OUTPUT
12264         else if (c == 0x100 + '>') { /* this flags &> redirection */
12265                 np->nfile.fd = 1;
12266                 pgetc(); /* this is '>', no need to check */
12267                 np->type = NTO2;
12268         }
12269 #endif
12270         else { /* c == '<' */
12271                 /*np->nfile.fd = 0; - stzalloc did it */
12272                 c = pgetc_eatbnl();
12273                 switch (c) {
12274                 case '<':
12275                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12276                                 np = stzalloc(sizeof(struct nhere));
12277                                 /*np->nfile.fd = 0; - stzalloc did it */
12278                         }
12279                         np->type = NHERE;
12280                         heredoc = stzalloc(sizeof(struct heredoc));
12281                         heredoc->here = np;
12282                         c = pgetc_eatbnl();
12283                         if (c == '-') {
12284                                 heredoc->striptabs = 1;
12285                         } else {
12286                                 /*heredoc->striptabs = 0; - stzalloc did it */
12287                                 pungetc();
12288                         }
12289                         break;
12290
12291                 case '&':
12292                         np->type = NFROMFD;
12293                         break;
12294
12295                 case '>':
12296                         np->type = NFROMTO;
12297                         break;
12298
12299                 default:
12300                         np->type = NFROM;
12301                         pungetc();
12302                         break;
12303                 }
12304         }
12305         if (fd >= 0)
12306                 np->nfile.fd = fd;
12307         redirnode = np;
12308         goto parseredir_return;
12309 }
12310
12311 /*
12312  * Parse a substitution.  At this point, we have read the dollar sign
12313  * and nothing else.
12314  */
12315
12316 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12317  * (assuming ascii char codes, as the original implementation did) */
12318 #define is_special(c) \
12319         (((unsigned)(c) - 33 < 32) \
12320                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12321 parsesub: {
12322         unsigned char subtype;
12323         int typeloc;
12324
12325         c = pgetc_eatbnl();
12326         if ((checkkwd & CHKEOFMARK)
12327          || c > 255 /* PEOA or PEOF */
12328          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12329         ) {
12330 #if BASH_DOLLAR_SQUOTE
12331                 if (synstack->syntax != DQSYNTAX && c == '\'')
12332                         bash_dollar_squote = 1;
12333                 else
12334 #endif
12335                         USTPUTC('$', out);
12336                 pungetc();
12337         } else if (c == '(') {
12338                 /* $(command) or $((arith)) */
12339                 if (pgetc_eatbnl() == '(') {
12340 #if ENABLE_FEATURE_SH_MATH
12341                         PARSEARITH();
12342 #else
12343                         raise_error_syntax("support for $((arith)) is disabled");
12344 #endif
12345                 } else {
12346                         pungetc();
12347                         PARSEBACKQNEW();
12348                 }
12349         } else {
12350                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12351                 smalluint newsyn = synstack->syntax;
12352
12353                 USTPUTC(CTLVAR, out);
12354                 typeloc = out - (char *)stackblock();
12355                 STADJUST(1, out);
12356                 subtype = VSNORMAL;
12357                 if (c == '{') {
12358                         c = pgetc_eatbnl();
12359                         subtype = 0;
12360                 }
12361  varname:
12362                 if (is_name(c)) {
12363                         /* $[{[#]]NAME[}] */
12364                         do {
12365                                 STPUTC(c, out);
12366                                 c = pgetc_eatbnl();
12367                         } while (is_in_name(c));
12368                 } else if (isdigit(c)) {
12369                         /* $[{[#]]NUM[}] */
12370                         do {
12371                                 STPUTC(c, out);
12372                                 c = pgetc_eatbnl();
12373                         } while (isdigit(c));
12374                 } else {
12375                         /* $[{[#]]<specialchar>[}] */
12376                         int cc = c;
12377
12378                         c = pgetc_eatbnl();
12379                         if (!subtype && cc == '#') {
12380                                 subtype = VSLENGTH;
12381                                 if (c == '_' || isalnum(c))
12382                                         goto varname;
12383                                 cc = c;
12384                                 c = pgetc_eatbnl();
12385                                 if (cc == '}' || c != '}') {
12386                                         pungetc();
12387                                         subtype = 0;
12388                                         c = cc;
12389                                         cc = '#';
12390                                 }
12391                         }
12392
12393                         if (!is_special(cc)) {
12394                                 if (subtype == VSLENGTH)
12395                                         subtype = 0;
12396                                 goto badsub;
12397                         }
12398
12399                         USTPUTC(cc, out);
12400                 }
12401
12402                 if (c != '}' && subtype == VSLENGTH) {
12403                         /* ${#VAR didn't end with } */
12404                         goto badsub;
12405                 }
12406
12407                 if (subtype == 0) {
12408                         static const char types[] ALIGN1 = "}-+?=";
12409                         /* ${VAR...} but not $VAR or ${#VAR} */
12410                         /* c == first char after VAR */
12411                         int cc = c;
12412
12413                         switch (c) {
12414                         case ':':
12415                                 c = pgetc_eatbnl();
12416 #if BASH_SUBSTR
12417                                 /* This check is only needed to not misinterpret
12418                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12419                                  * constructs.
12420                                  */
12421                                 if (!strchr(types, c)) {
12422                                         subtype = VSSUBSTR;
12423                                         pungetc();
12424                                         break; /* "goto badsub" is bigger (!) */
12425                                 }
12426 #endif
12427                                 subtype = VSNUL;
12428                                 /*FALLTHROUGH*/
12429                         default: {
12430                                 const char *p = strchr(types, c);
12431                                 if (p == NULL)
12432                                         break;
12433                                 subtype |= p - types + VSNORMAL;
12434                                 break;
12435                         }
12436                         case '%':
12437                         case '#':
12438                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12439                                 c = pgetc_eatbnl();
12440                                 if (c == cc)
12441                                         subtype++;
12442                                 else
12443                                         pungetc();
12444
12445                                 newsyn = BASESYNTAX;
12446                                 break;
12447 #if BASH_PATTERN_SUBST
12448                         case '/':
12449                                 /* ${v/[/]pattern/repl} */
12450 //TODO: encode pattern and repl separately.
12451 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12452 // are broken (should print "ONE")
12453                                 subtype = VSREPLACE;
12454                                 newsyn = BASESYNTAX;
12455                                 c = pgetc_eatbnl();
12456                                 if (c != '/')
12457                                         goto badsub;
12458                                 subtype++; /* VSREPLACEALL */
12459                                 break;
12460 #endif
12461                         }
12462                 } else {
12463  badsub:
12464                         pungetc();
12465                 }
12466
12467                 if (newsyn == ARISYNTAX && subtype > VSNORMAL)
12468                         newsyn = DQSYNTAX;
12469
12470                 if (newsyn != synstack->syntax) {
12471                         synstack_push(&synstack,
12472                                 synstack->prev ?: alloca(sizeof(*synstack)),
12473                                 newsyn);
12474
12475                         synstack->varpushed = 1;
12476                         synstack->dblquote = newsyn != BASESYNTAX;
12477                 }
12478
12479                 ((unsigned char *)stackblock())[typeloc] = subtype;
12480                 if (subtype != VSNORMAL) {
12481                         synstack->varnest++;
12482                         if (synstack->dblquote)
12483                                 synstack->dqvarnest++;
12484                 }
12485                 STPUTC('=', out);
12486         }
12487         goto parsesub_return;
12488 }
12489
12490 /*
12491  * Called to parse command substitutions.  Newstyle is set if the command
12492  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12493  * list of commands (passed by reference), and savelen is the number of
12494  * characters on the top of the stack which must be preserved.
12495  */
12496 parsebackq: {
12497         struct nodelist **nlpp;
12498         union node *n;
12499         char *str;
12500         size_t savelen;
12501         smallint saveprompt = 0;
12502
12503         str = NULL;
12504         savelen = out - (char *)stackblock();
12505         if (savelen > 0) {
12506                 /*
12507                  * FIXME: this can allocate very large block on stack and SEGV.
12508                  * Example:
12509                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12510                  * allocates 100kb for every command subst. With about
12511                  * a hundred command substitutions stack overflows.
12512                  * With larger prepended string, SEGV happens sooner.
12513                  */
12514                 str = alloca(savelen);
12515                 memcpy(str, stackblock(), savelen);
12516         }
12517
12518         if (oldstyle) {
12519                 /* We must read until the closing backquote, giving special
12520                  * treatment to some slashes, and then push the string and
12521                  * reread it as input, interpreting it normally.
12522                  */
12523                 char *pout;
12524                 size_t psavelen;
12525                 char *pstr;
12526
12527                 STARTSTACKSTR(pout);
12528                 for (;;) {
12529                         int pc;
12530
12531                         setprompt_if(needprompt, 2);
12532                         pc = pgetc_eatbnl();
12533                         switch (pc) {
12534                         case '`':
12535                                 goto done;
12536
12537                         case '\\':
12538                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12539                                 if (pc != '\\' && pc != '`' && pc != '$'
12540                                  && (!synstack->dblquote || pc != '"')
12541                                 ) {
12542                                         STPUTC('\\', pout);
12543                                 }
12544                                 if (pc <= 255 /* not PEOA or PEOF */) {
12545                                         break;
12546                                 }
12547                                 /* fall through */
12548
12549                         case PEOF:
12550                         IF_ASH_ALIAS(case PEOA:)
12551                                 raise_error_syntax("EOF in backquote substitution");
12552
12553                         case '\n':
12554                                 nlnoprompt();
12555                                 break;
12556
12557                         default:
12558                                 break;
12559                         }
12560                         STPUTC(pc, pout);
12561                 }
12562  done:
12563                 STPUTC('\0', pout);
12564                 psavelen = pout - (char *)stackblock();
12565                 if (psavelen > 0) {
12566                         pstr = grabstackstr(pout);
12567                         setinputstring(pstr);
12568                 }
12569         }
12570         nlpp = &bqlist;
12571         while (*nlpp)
12572                 nlpp = &(*nlpp)->next;
12573         *nlpp = stzalloc(sizeof(**nlpp));
12574         /* (*nlpp)->next = NULL; - stzalloc did it */
12575
12576         if (oldstyle) {
12577                 saveprompt = doprompt;
12578                 doprompt = 0;
12579         }
12580
12581         n = list(2);
12582
12583         if (oldstyle)
12584                 doprompt = saveprompt;
12585         else if (readtoken() != TRP)
12586                 raise_error_unexpected_syntax(TRP);
12587
12588         (*nlpp)->n = n;
12589         if (oldstyle) {
12590                 /*
12591                  * Start reading from old file again, ignoring any pushed back
12592                  * tokens left from the backquote parsing
12593                  */
12594                 popfile();
12595                 tokpushback = 0;
12596         }
12597         while (stackblocksize() <= savelen)
12598                 growstackblock();
12599         STARTSTACKSTR(out);
12600         if (str) {
12601                 memcpy(out, str, savelen);
12602                 STADJUST(savelen, out);
12603         }
12604         USTPUTC(CTLBACKQ, out);
12605         if (oldstyle)
12606                 goto parsebackq_oldreturn;
12607         goto parsebackq_newreturn;
12608 }
12609
12610 #if ENABLE_FEATURE_SH_MATH
12611 /*
12612  * Parse an arithmetic expansion (indicate start of one and set state)
12613  */
12614 parsearith: {
12615
12616         synstack_push(&synstack,
12617                         synstack->prev ?: alloca(sizeof(*synstack)),
12618                         ARISYNTAX);
12619         synstack->dblquote = 1;
12620         USTPUTC(CTLARI, out);
12621         goto parsearith_return;
12622 }
12623 #endif
12624 } /* end of readtoken */
12625
12626 /*
12627  * Read the next input token.
12628  * If the token is a word, we set backquotelist to the list of cmds in
12629  *      backquotes.  We set quoteflag to true if any part of the word was
12630  *      quoted.
12631  * If the token is TREDIR, then we set redirnode to a structure containing
12632  *      the redirection.
12633  *
12634  * [Change comment:  here documents and internal procedures]
12635  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12636  *  word parsing code into a separate routine.  In this case, readtoken
12637  *  doesn't need to have any internal procedures, but parseword does.
12638  *  We could also make parseoperator in essence the main routine, and
12639  *  have parseword (readtoken1?) handle both words and redirection.]
12640  */
12641 #define NEW_xxreadtoken
12642 #ifdef NEW_xxreadtoken
12643 /* singles must be first! */
12644 static const char xxreadtoken_chars[7] ALIGN1 = {
12645         '\n', '(', ')', /* singles */
12646         '&', '|', ';',  /* doubles */
12647         0
12648 };
12649
12650 #define xxreadtoken_singles 3
12651 #define xxreadtoken_doubles 3
12652
12653 static const char xxreadtoken_tokens[] ALIGN1 = {
12654         TNL, TLP, TRP,          /* only single occurrence allowed */
12655         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12656         TEOF,                   /* corresponds to trailing nul */
12657         TAND, TOR, TENDCASE     /* if double occurrence */
12658 };
12659
12660 static int
12661 xxreadtoken(void)
12662 {
12663         int c;
12664
12665         if (tokpushback) {
12666                 tokpushback = 0;
12667                 return lasttoken;
12668         }
12669         setprompt_if(needprompt, 2);
12670         for (;;) {                      /* until token or start of word found */
12671                 c = pgetc_eatbnl();
12672                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12673                         continue;
12674
12675                 if (c == '#') {
12676                         while ((c = pgetc()) != '\n' && c != PEOF)
12677                                 continue;
12678                         pungetc();
12679                 } else if (c == '\\') {
12680                         break; /* return readtoken1(...) */
12681                 } else {
12682                         const char *p;
12683
12684                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12685                         if (c != PEOF) {
12686                                 if (c == '\n') {
12687                                         nlnoprompt();
12688                                 }
12689
12690                                 p = strchr(xxreadtoken_chars, c);
12691                                 if (p == NULL)
12692                                         break; /* return readtoken1(...) */
12693
12694                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12695                                         int cc = pgetc_eatbnl();
12696                                         if (cc == c) {    /* double occurrence? */
12697                                                 p += xxreadtoken_doubles + 1;
12698                                         } else {
12699                                                 pungetc();
12700 #if BASH_REDIR_OUTPUT
12701                                                 if (c == '&' && cc == '>') /* &> */
12702                                                         break; /* return readtoken1(...) */
12703 #endif
12704                                         }
12705                                 }
12706                         }
12707                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12708                         return lasttoken;
12709                 }
12710         } /* for (;;) */
12711
12712         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12713 }
12714 #else /* old xxreadtoken */
12715 #define RETURN(token)   return lasttoken = token
12716 static int
12717 xxreadtoken(void)
12718 {
12719         int c;
12720
12721         if (tokpushback) {
12722                 tokpushback = 0;
12723                 return lasttoken;
12724         }
12725         setprompt_if(needprompt, 2);
12726         for (;;) {      /* until token or start of word found */
12727                 c = pgetc_eatbnl();
12728                 switch (c) {
12729                 case ' ': case '\t':
12730                 IF_ASH_ALIAS(case PEOA:)
12731                         continue;
12732                 case '#':
12733                         while ((c = pgetc()) != '\n' && c != PEOF)
12734                                 continue;
12735                         pungetc();
12736                         continue;
12737                 case '\n':
12738                         nlnoprompt();
12739                         RETURN(TNL);
12740                 case PEOF:
12741                         RETURN(TEOF);
12742                 case '&':
12743                         if (pgetc_eatbnl() == '&')
12744                                 RETURN(TAND);
12745                         pungetc();
12746                         RETURN(TBACKGND);
12747                 case '|':
12748                         if (pgetc_eatbnl() == '|')
12749                                 RETURN(TOR);
12750                         pungetc();
12751                         RETURN(TPIPE);
12752                 case ';':
12753                         if (pgetc_eatbnl() == ';')
12754                                 RETURN(TENDCASE);
12755                         pungetc();
12756                         RETURN(TSEMI);
12757                 case '(':
12758                         RETURN(TLP);
12759                 case ')':
12760                         RETURN(TRP);
12761                 }
12762                 break;
12763         }
12764         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12765 #undef RETURN
12766 }
12767 #endif /* old xxreadtoken */
12768
12769 static int
12770 readtoken(void)
12771 {
12772         int t;
12773         int kwd = checkkwd;
12774 #if DEBUG
12775         smallint alreadyseen = tokpushback;
12776 #endif
12777
12778 #if ENABLE_ASH_ALIAS
12779  top:
12780 #endif
12781
12782         t = xxreadtoken();
12783
12784         /*
12785          * eat newlines
12786          */
12787         if (kwd & CHKNL) {
12788                 while (t == TNL) {
12789                         parseheredoc();
12790                         t = xxreadtoken();
12791                 }
12792         }
12793
12794         if (t != TWORD || quoteflag) {
12795                 goto out;
12796         }
12797
12798         /*
12799          * check for keywords
12800          */
12801         if (kwd & CHKKWD) {
12802                 const char *const *pp;
12803
12804                 pp = findkwd(wordtext);
12805                 if (pp) {
12806                         lasttoken = t = pp - tokname_array;
12807                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12808                         goto out;
12809                 }
12810         }
12811
12812         if (checkkwd & CHKALIAS) {
12813 #if ENABLE_ASH_ALIAS
12814                 struct alias *ap;
12815                 ap = lookupalias(wordtext, 1);
12816                 if (ap != NULL) {
12817                         if (*ap->val) {
12818                                 pushstring(ap->val, ap);
12819                         }
12820                         goto top;
12821                 }
12822 #endif
12823         }
12824  out:
12825         checkkwd = 0;
12826 #if DEBUG
12827         if (!alreadyseen)
12828                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12829         else
12830                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12831 #endif
12832         return t;
12833 }
12834
12835 static int
12836 peektoken(void)
12837 {
12838         int t;
12839
12840         t = readtoken();
12841         tokpushback = 1;
12842         return t;
12843 }
12844
12845 /*
12846  * Read and parse a command.  Returns NODE_EOF on end of file.
12847  * (NULL is a valid parse tree indicating a blank line.)
12848  */
12849 static union node *
12850 parsecmd(int interact)
12851 {
12852         tokpushback = 0;
12853         checkkwd = 0;
12854         heredoclist = 0;
12855         doprompt = interact;
12856         setprompt_if(doprompt, doprompt);
12857         needprompt = 0;
12858         return list(1);
12859 }
12860
12861 /*
12862  * Input any here documents.
12863  */
12864 static void
12865 parseheredoc(void)
12866 {
12867         struct heredoc *here;
12868         union node *n;
12869
12870         here = heredoclist;
12871         heredoclist = NULL;
12872
12873         while (here) {
12874                 setprompt_if(needprompt, 2);
12875                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12876                                 here->eofmark, here->striptabs);
12877                 n = stzalloc(sizeof(struct narg));
12878                 n->narg.type = NARG;
12879                 /*n->narg.next = NULL; - stzalloc did it */
12880                 n->narg.text = wordtext;
12881                 n->narg.backquote = backquotelist;
12882                 here->here->nhere.doc = n;
12883                 here = here->next;
12884         }
12885 }
12886
12887
12888 static const char *
12889 expandstr(const char *ps, int syntax_type)
12890 {
12891         union node n;
12892         int saveprompt;
12893
12894         /* XXX Fix (char *) cast. */
12895         setinputstring((char *)ps);
12896
12897         saveprompt = doprompt;
12898         doprompt = 0;
12899
12900         /* readtoken1() might die horribly.
12901          * Try a prompt with syntactically wrong command:
12902          * PS1='$(date "+%H:%M:%S) > '
12903          */
12904         {
12905                 volatile int saveint;
12906                 struct jmploc *volatile savehandler = exception_handler;
12907                 struct jmploc jmploc;
12908                 SAVE_INT(saveint);
12909                 if (setjmp(jmploc.loc) == 0) {
12910                         exception_handler = &jmploc;
12911                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12912                 }
12913                 exception_handler = savehandler;
12914                 RESTORE_INT(saveint);
12915         }
12916
12917         doprompt = saveprompt;
12918
12919         popfile();
12920
12921         n.narg.type = NARG;
12922         n.narg.next = NULL;
12923         n.narg.text = wordtext;
12924         n.narg.backquote = backquotelist;
12925
12926         expandarg(&n, NULL, EXP_QUOTED);
12927         return stackblock();
12928 }
12929
12930 static inline int
12931 parser_eof(void)
12932 {
12933         return tokpushback && lasttoken == TEOF;
12934 }
12935
12936 /*
12937  * Execute a command or commands contained in a string.
12938  */
12939 static int
12940 evalstring(char *s, int flags)
12941 {
12942         struct jmploc *volatile savehandler;
12943         struct jmploc jmploc;
12944         int ex;
12945
12946         union node *n;
12947         struct stackmark smark;
12948         int status;
12949
12950         s = sstrdup(s);
12951         setinputstring(s);
12952         setstackmark(&smark);
12953
12954         status = 0;
12955         /* On exception inside execution loop, we must popfile().
12956          * Try interactively:
12957          *      readonly a=a
12958          *      command eval "a=b"  # throws "is read only" error
12959          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12960          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12961          */
12962         savehandler = exception_handler;
12963         ex = setjmp(jmploc.loc);
12964         if (ex)
12965                 goto out;
12966         exception_handler = &jmploc;
12967
12968         while ((n = parsecmd(0)) != NODE_EOF) {
12969                 int i;
12970
12971                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12972                 if (n)
12973                         status = i;
12974                 popstackmark(&smark);
12975                 if (evalskip)
12976                         break;
12977         }
12978  out:
12979         popstackmark(&smark);
12980         popfile();
12981         stunalloc(s);
12982
12983         exception_handler = savehandler;
12984         if (ex)
12985                 longjmp(exception_handler->loc, ex);
12986
12987         return status;
12988 }
12989
12990 /*
12991  * The eval command.
12992  */
12993 static int FAST_FUNC
12994 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12995 {
12996         char *p;
12997         char *concat;
12998
12999         if (argv[1]) {
13000                 p = argv[1];
13001                 argv += 2;
13002                 if (argv[0]) {
13003                         STARTSTACKSTR(concat);
13004                         for (;;) {
13005                                 concat = stack_putstr(p, concat);
13006                                 p = *argv++;
13007                                 if (p == NULL)
13008                                         break;
13009                                 STPUTC(' ', concat);
13010                         }
13011                         STPUTC('\0', concat);
13012                         p = grabstackstr(concat);
13013                 }
13014                 return evalstring(p, flags & EV_TESTED);
13015         }
13016         return 0;
13017 }
13018
13019 /*
13020  * Read and execute commands.
13021  * "Top" is nonzero for the top level command loop;
13022  * it turns on prompting if the shell is interactive.
13023  */
13024 static int
13025 cmdloop(int top)
13026 {
13027         union node *n;
13028         struct stackmark smark;
13029         int inter;
13030         int status = 0;
13031         int numeof = 0;
13032
13033         TRACE(("cmdloop(%d) called\n", top));
13034         for (;;) {
13035                 int skip;
13036
13037                 setstackmark(&smark);
13038 #if JOBS
13039                 if (doing_jobctl)
13040                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13041 #endif
13042                 inter = 0;
13043                 if (iflag && top) {
13044                         inter++;
13045                         chkmail();
13046                 }
13047                 n = parsecmd(inter);
13048 #if DEBUG
13049                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13050                         showtree(n);
13051 #endif
13052                 if (n == NODE_EOF) {
13053                         if (!top || numeof >= 50)
13054                                 break;
13055                         if (!stoppedjobs()) {
13056                                 if (!Iflag)
13057                                         break;
13058                                 out2str("\nUse \"exit\" to leave shell.\n");
13059                         }
13060                         numeof++;
13061                 } else if (nflag == 0) {
13062                         int i;
13063
13064                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13065                         job_warning >>= 1;
13066                         numeof = 0;
13067                         i = evaltree(n, 0);
13068                         if (n)
13069                                 status = i;
13070                 }
13071                 popstackmark(&smark);
13072                 skip = evalskip;
13073
13074                 if (skip) {
13075                         evalskip &= ~SKIPFUNC;
13076                         break;
13077                 }
13078         }
13079         return status;
13080 }
13081
13082 /*
13083  * Take commands from a file.  To be compatible we should do a path
13084  * search for the file, which is necessary to find sub-commands.
13085  */
13086 static char *
13087 find_dot_file(char *name)
13088 {
13089         char *fullname;
13090         const char *path = pathval();
13091         struct stat statb;
13092
13093         /* don't try this for absolute or relative paths */
13094         if (strchr(name, '/'))
13095                 return name;
13096
13097         while ((fullname = path_advance(&path, name)) != NULL) {
13098                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13099                         /*
13100                          * Don't bother freeing here, since it will
13101                          * be freed by the caller.
13102                          */
13103                         return fullname;
13104                 }
13105                 if (fullname != name)
13106                         stunalloc(fullname);
13107         }
13108         /* not found in PATH */
13109
13110 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13111         return name;
13112 #else
13113         ash_msg_and_raise_error("%s: not found", name);
13114         /* NOTREACHED */
13115 #endif
13116 }
13117
13118 static int FAST_FUNC
13119 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13120 {
13121         /* "false; . empty_file; echo $?" should print 0, not 1: */
13122         int status = 0;
13123         char *fullname;
13124         char **argv;
13125         char *args_need_save;
13126         volatile struct shparam saveparam;
13127
13128 //???
13129 //      struct strlist *sp;
13130 //      for (sp = cmdenviron; sp; sp = sp->next)
13131 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13132
13133         nextopt(nullstr); /* handle possible "--" */
13134         argv = argptr;
13135
13136         if (!argv[0]) {
13137                 /* bash says: "bash: .: filename argument required" */
13138                 return 2; /* bash compat */
13139         }
13140
13141         /* This aborts if file isn't found, which is POSIXly correct.
13142          * bash returns exitcode 1 instead.
13143          */
13144         fullname = find_dot_file(argv[0]);
13145         argv++;
13146         args_need_save = argv[0];
13147         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13148                 int argc;
13149                 saveparam = shellparam;
13150                 shellparam.malloced = 0;
13151                 argc = 1;
13152                 while (argv[argc])
13153                         argc++;
13154                 shellparam.nparam = argc;
13155                 shellparam.p = argv;
13156         };
13157
13158         /* This aborts if file can't be opened, which is POSIXly correct.
13159          * bash returns exitcode 1 instead.
13160          */
13161         setinputfile(fullname, INPUT_PUSH_FILE);
13162         commandname = fullname;
13163         status = cmdloop(0);
13164         popfile();
13165
13166         if (args_need_save) {
13167                 freeparam(&shellparam);
13168                 shellparam = saveparam;
13169         };
13170
13171         return status;
13172 }
13173
13174 static int FAST_FUNC
13175 exitcmd(int argc UNUSED_PARAM, char **argv)
13176 {
13177         if (stoppedjobs())
13178                 return 0;
13179         if (argv[1])
13180                 exitstatus = number(argv[1]);
13181         raise_exception(EXEXIT);
13182         /* NOTREACHED */
13183 }
13184
13185 /*
13186  * Read a file containing shell functions.
13187  */
13188 static void
13189 readcmdfile(char *name)
13190 {
13191         setinputfile(name, INPUT_PUSH_FILE);
13192         cmdloop(0);
13193         popfile();
13194 }
13195
13196
13197 /* ============ find_command inplementation */
13198
13199 /*
13200  * Resolve a command name.  If you change this routine, you may have to
13201  * change the shellexec routine as well.
13202  */
13203 static void
13204 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13205 {
13206         struct tblentry *cmdp;
13207         int idx;
13208         int prev;
13209         char *fullname;
13210         struct stat statb;
13211         int e;
13212         int updatetbl;
13213         struct builtincmd *bcmd;
13214
13215         /* If name contains a slash, don't use PATH or hash table */
13216         if (strchr(name, '/') != NULL) {
13217                 entry->u.index = -1;
13218                 if (act & DO_ABS) {
13219                         while (stat(name, &statb) < 0) {
13220 #ifdef SYSV
13221                                 if (errno == EINTR)
13222                                         continue;
13223 #endif
13224                                 entry->cmdtype = CMDUNKNOWN;
13225                                 return;
13226                         }
13227                 }
13228                 entry->cmdtype = CMDNORMAL;
13229                 return;
13230         }
13231
13232 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13233
13234         updatetbl = (path == pathval());
13235         if (!updatetbl) {
13236                 act |= DO_ALTPATH;
13237                 if (strstr(path, "%builtin") != NULL)
13238                         act |= DO_ALTBLTIN;
13239         }
13240
13241         /* If name is in the table, check answer will be ok */
13242         cmdp = cmdlookup(name, 0);
13243         if (cmdp != NULL) {
13244                 int bit;
13245
13246                 switch (cmdp->cmdtype) {
13247                 default:
13248 #if DEBUG
13249                         abort();
13250 #endif
13251                 case CMDNORMAL:
13252                         bit = DO_ALTPATH;
13253                         break;
13254                 case CMDFUNCTION:
13255                         bit = DO_NOFUNC;
13256                         break;
13257                 case CMDBUILTIN:
13258                         bit = DO_ALTBLTIN;
13259                         break;
13260                 }
13261                 if (act & bit) {
13262                         updatetbl = 0;
13263                         cmdp = NULL;
13264                 } else if (cmdp->rehash == 0)
13265                         /* if not invalidated by cd, we're done */
13266                         goto success;
13267         }
13268
13269         /* If %builtin not in path, check for builtin next */
13270         bcmd = find_builtin(name);
13271         if (bcmd) {
13272                 if (IS_BUILTIN_REGULAR(bcmd))
13273                         goto builtin_success;
13274                 if (act & DO_ALTPATH) {
13275                         if (!(act & DO_ALTBLTIN))
13276                                 goto builtin_success;
13277                 } else if (builtinloc <= 0) {
13278                         goto builtin_success;
13279                 }
13280         }
13281
13282 #if ENABLE_FEATURE_SH_STANDALONE
13283         {
13284                 int applet_no = find_applet_by_name(name);
13285                 if (applet_no >= 0) {
13286                         entry->cmdtype = CMDNORMAL;
13287                         entry->u.index = -2 - applet_no;
13288                         return;
13289                 }
13290         }
13291 #endif
13292
13293         /* We have to search path. */
13294         prev = -1;              /* where to start */
13295         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13296                 if (cmdp->cmdtype == CMDBUILTIN)
13297                         prev = builtinloc;
13298                 else
13299                         prev = cmdp->param.index;
13300         }
13301
13302         e = ENOENT;
13303         idx = -1;
13304  loop:
13305         while ((fullname = path_advance(&path, name)) != NULL) {
13306                 stunalloc(fullname);
13307                 /* NB: code below will still use fullname
13308                  * despite it being "unallocated" */
13309                 idx++;
13310                 if (pathopt) {
13311                         if (prefix(pathopt, "builtin")) {
13312                                 if (bcmd)
13313                                         goto builtin_success;
13314                                 continue;
13315                         }
13316                         if ((act & DO_NOFUNC)
13317                          || !prefix(pathopt, "func")
13318                         ) {     /* ignore unimplemented options */
13319                                 continue;
13320                         }
13321                 }
13322                 /* if rehash, don't redo absolute path names */
13323                 if (fullname[0] == '/' && idx <= prev) {
13324                         if (idx < prev)
13325                                 continue;
13326                         TRACE(("searchexec \"%s\": no change\n", name));
13327                         goto success;
13328                 }
13329                 while (stat(fullname, &statb) < 0) {
13330 #ifdef SYSV
13331                         if (errno == EINTR)
13332                                 continue;
13333 #endif
13334                         if (errno != ENOENT && errno != ENOTDIR)
13335                                 e = errno;
13336                         goto loop;
13337                 }
13338                 e = EACCES;     /* if we fail, this will be the error */
13339                 if (!S_ISREG(statb.st_mode))
13340                         continue;
13341                 if (pathopt) {          /* this is a %func directory */
13342                         stalloc(strlen(fullname) + 1);
13343                         /* NB: stalloc will return space pointed by fullname
13344                          * (because we don't have any intervening allocations
13345                          * between stunalloc above and this stalloc) */
13346                         readcmdfile(fullname);
13347                         cmdp = cmdlookup(name, 0);
13348                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13349                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13350                         stunalloc(fullname);
13351                         goto success;
13352                 }
13353                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13354                 if (!updatetbl) {
13355                         entry->cmdtype = CMDNORMAL;
13356                         entry->u.index = idx;
13357                         return;
13358                 }
13359                 INT_OFF;
13360                 cmdp = cmdlookup(name, 1);
13361                 cmdp->cmdtype = CMDNORMAL;
13362                 cmdp->param.index = idx;
13363                 INT_ON;
13364                 goto success;
13365         }
13366
13367         /* We failed.  If there was an entry for this command, delete it */
13368         if (cmdp && updatetbl)
13369                 delete_cmd_entry();
13370         if (act & DO_ERR) {
13371 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13372                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13373                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13374                         char *argv[3];
13375                         argv[0] = (char*) "command_not_found_handle";
13376                         argv[1] = name;
13377                         argv[2] = NULL;
13378                         evalfun(hookp->param.func, 2, argv, 0);
13379                         entry->cmdtype = CMDUNKNOWN;
13380                         return;
13381                 }
13382 #endif
13383                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13384         }
13385         entry->cmdtype = CMDUNKNOWN;
13386         return;
13387
13388  builtin_success:
13389         if (!updatetbl) {
13390                 entry->cmdtype = CMDBUILTIN;
13391                 entry->u.cmd = bcmd;
13392                 return;
13393         }
13394         INT_OFF;
13395         cmdp = cmdlookup(name, 1);
13396         cmdp->cmdtype = CMDBUILTIN;
13397         cmdp->param.cmd = bcmd;
13398         INT_ON;
13399  success:
13400         cmdp->rehash = 0;
13401         entry->cmdtype = cmdp->cmdtype;
13402         entry->u = cmdp->param;
13403 }
13404
13405
13406 /*
13407  * The trap builtin.
13408  */
13409 static int FAST_FUNC
13410 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13411 {
13412         char *action;
13413         char **ap;
13414         int signo, exitcode;
13415
13416         nextopt(nullstr);
13417         ap = argptr;
13418         if (!*ap) {
13419                 for (signo = 0; signo < NSIG; signo++) {
13420                         char *tr = trap_ptr[signo];
13421                         if (tr) {
13422                                 /* note: bash adds "SIG", but only if invoked
13423                                  * as "bash". If called as "sh", or if set -o posix,
13424                                  * then it prints short signal names.
13425                                  * We are printing short names: */
13426                                 out1fmt("trap -- %s %s\n",
13427                                                 single_quote(tr),
13428                                                 get_signame(signo));
13429                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13430                  * In this case, we will exit very soon, no need to free(). */
13431                                 /* if (trap_ptr != trap && tp[0]) */
13432                                 /*      free(tr); */
13433                         }
13434                 }
13435                 /*
13436                 if (trap_ptr != trap) {
13437                         free(trap_ptr);
13438                         trap_ptr = trap;
13439                 }
13440                 */
13441                 return 0;
13442         }
13443
13444         /* Why the second check?
13445          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13446          * In this case, NUM is signal no, not an action.
13447          */
13448         action = NULL;
13449         if (ap[1] && !is_number(ap[0]))
13450                 action = *ap++;
13451
13452         exitcode = 0;
13453         while (*ap) {
13454                 signo = get_signum(*ap);
13455                 if (signo < 0) {
13456                         /* Mimic bash message exactly */
13457                         ash_msg("%s: invalid signal specification", *ap);
13458                         exitcode = 1;
13459                         goto next;
13460                 }
13461                 INT_OFF;
13462                 if (action) {
13463                         if (LONE_DASH(action))
13464                                 action = NULL;
13465                         else {
13466                                 if (action[0]) /* not NULL and not "" and not "-" */
13467                                         may_have_traps = 1;
13468                                 action = ckstrdup(action);
13469                         }
13470                 }
13471                 free(trap[signo]);
13472                 trap[signo] = action;
13473                 if (signo != 0)
13474                         setsignal(signo);
13475                 INT_ON;
13476  next:
13477                 ap++;
13478         }
13479         return exitcode;
13480 }
13481
13482
13483 /* ============ Builtins */
13484
13485 #if ENABLE_ASH_HELP
13486 static int FAST_FUNC
13487 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13488 {
13489         unsigned col;
13490         unsigned i;
13491
13492         out1fmt(
13493                 "Built-in commands:\n"
13494                 "------------------\n");
13495         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13496                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13497                                         builtintab[i].name + 1);
13498                 if (col > 60) {
13499                         out1fmt("\n");
13500                         col = 0;
13501                 }
13502         }
13503 # if ENABLE_FEATURE_SH_STANDALONE
13504         {
13505                 const char *a = applet_names;
13506                 while (*a) {
13507                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13508                         if (col > 60) {
13509                                 out1fmt("\n");
13510                                 col = 0;
13511                         }
13512                         while (*a++ != '\0')
13513                                 continue;
13514                 }
13515         }
13516 # endif
13517         newline_and_flush(stdout);
13518         return EXIT_SUCCESS;
13519 }
13520 #endif
13521
13522 #if MAX_HISTORY
13523 static int FAST_FUNC
13524 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13525 {
13526         show_history(line_input_state);
13527         return EXIT_SUCCESS;
13528 }
13529 #endif
13530
13531 /*
13532  * The export and readonly commands.
13533  */
13534 static int FAST_FUNC
13535 exportcmd(int argc UNUSED_PARAM, char **argv)
13536 {
13537         struct var *vp;
13538         char *name;
13539         const char *p;
13540         char **aptr;
13541         char opt;
13542         int flag;
13543         int flag_off;
13544
13545         /* "readonly" in bash accepts, but ignores -n.
13546          * We do the same: it saves a conditional in nextopt's param.
13547          */
13548         flag_off = 0;
13549         while ((opt = nextopt("np")) != '\0') {
13550                 if (opt == 'n')
13551                         flag_off = VEXPORT;
13552         }
13553         flag = VEXPORT;
13554         if (argv[0][0] == 'r') {
13555                 flag = VREADONLY;
13556                 flag_off = 0; /* readonly ignores -n */
13557         }
13558         flag_off = ~flag_off;
13559
13560         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13561         {
13562                 aptr = argptr;
13563                 name = *aptr;
13564                 if (name) {
13565                         do {
13566                                 p = strchr(name, '=');
13567                                 if (p != NULL) {
13568                                         p++;
13569                                 } else {
13570                                         vp = *findvar(hashvar(name), name);
13571                                         if (vp) {
13572                                                 vp->flags = ((vp->flags | flag) & flag_off);
13573                                                 continue;
13574                                         }
13575                                 }
13576                                 setvar(name, p, (flag & flag_off));
13577                         } while ((name = *++aptr) != NULL);
13578                         return 0;
13579                 }
13580         }
13581
13582         /* No arguments. Show the list of exported or readonly vars.
13583          * -n is ignored.
13584          */
13585         showvars(argv[0], flag, 0);
13586         return 0;
13587 }
13588
13589 /*
13590  * Delete a function if it exists.
13591  */
13592 static void
13593 unsetfunc(const char *name)
13594 {
13595         struct tblentry *cmdp;
13596
13597         cmdp = cmdlookup(name, 0);
13598         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13599                 delete_cmd_entry();
13600 }
13601
13602 /*
13603  * The unset builtin command.  We unset the function before we unset the
13604  * variable to allow a function to be unset when there is a readonly variable
13605  * with the same name.
13606  */
13607 static int FAST_FUNC
13608 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13609 {
13610         char **ap;
13611         int i;
13612         int flag = 0;
13613
13614         while ((i = nextopt("vf")) != 0) {
13615                 flag = i;
13616         }
13617
13618         for (ap = argptr; *ap; ap++) {
13619                 if (flag != 'f') {
13620                         unsetvar(*ap);
13621                         continue;
13622                 }
13623                 if (flag != 'v')
13624                         unsetfunc(*ap);
13625         }
13626         return 0;
13627 }
13628
13629 static const unsigned char timescmd_str[] ALIGN1 = {
13630         ' ',  offsetof(struct tms, tms_utime),
13631         '\n', offsetof(struct tms, tms_stime),
13632         ' ',  offsetof(struct tms, tms_cutime),
13633         '\n', offsetof(struct tms, tms_cstime),
13634         0
13635 };
13636 static int FAST_FUNC
13637 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13638 {
13639         unsigned clk_tck;
13640         const unsigned char *p;
13641         struct tms buf;
13642
13643         clk_tck = bb_clk_tck();
13644
13645         times(&buf);
13646         p = timescmd_str;
13647         do {
13648                 unsigned sec, frac;
13649                 unsigned long t;
13650                 t = *(clock_t *)(((char *) &buf) + p[1]);
13651                 sec = t / clk_tck;
13652                 frac = t % clk_tck;
13653                 out1fmt("%um%u.%03us%c",
13654                         sec / 60, sec % 60,
13655                         (frac * 1000) / clk_tck,
13656                         p[0]);
13657                 p += 2;
13658         } while (*p);
13659
13660         return 0;
13661 }
13662
13663 #if ENABLE_FEATURE_SH_MATH
13664 /*
13665  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13666  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13667  *
13668  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13669  */
13670 static int FAST_FUNC
13671 letcmd(int argc UNUSED_PARAM, char **argv)
13672 {
13673         arith_t i;
13674
13675         argv++;
13676         if (!*argv)
13677                 ash_msg_and_raise_error("expression expected");
13678         do {
13679                 i = ash_arith(*argv);
13680         } while (*++argv);
13681
13682         return !i;
13683 }
13684 #endif
13685
13686 /*
13687  * The read builtin. Options:
13688  *      -r              Do not interpret '\' specially
13689  *      -s              Turn off echo (tty only)
13690  *      -n NCHARS       Read NCHARS max
13691  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13692  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13693  *      -u FD           Read from given FD instead of fd 0
13694  *      -d DELIM        End on DELIM char, not newline
13695  * This uses unbuffered input, which may be avoidable in some cases.
13696  * TODO: bash also has:
13697  *      -a ARRAY        Read into array[0],[1],etc
13698  *      -e              Use line editing (tty only)
13699  */
13700 static int FAST_FUNC
13701 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13702 {
13703         char *opt_n = NULL;
13704         char *opt_p = NULL;
13705         char *opt_t = NULL;
13706         char *opt_u = NULL;
13707         char *opt_d = NULL; /* optimized out if !BASH */
13708         int read_flags = 0;
13709         const char *r;
13710         int i;
13711
13712         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13713                 switch (i) {
13714                 case 'p':
13715                         opt_p = optionarg;
13716                         break;
13717                 case 'n':
13718                         opt_n = optionarg;
13719                         break;
13720                 case 's':
13721                         read_flags |= BUILTIN_READ_SILENT;
13722                         break;
13723                 case 't':
13724                         opt_t = optionarg;
13725                         break;
13726                 case 'r':
13727                         read_flags |= BUILTIN_READ_RAW;
13728                         break;
13729                 case 'u':
13730                         opt_u = optionarg;
13731                         break;
13732 #if BASH_READ_D
13733                 case 'd':
13734                         opt_d = optionarg;
13735                         break;
13736 #endif
13737                 default:
13738                         break;
13739                 }
13740         }
13741
13742         /* "read -s" needs to save/restore termios, can't allow ^C
13743          * to jump out of it.
13744          */
13745  again:
13746         INT_OFF;
13747         r = shell_builtin_read(setvar0,
13748                 argptr,
13749                 bltinlookup("IFS"), /* can be NULL */
13750                 read_flags,
13751                 opt_n,
13752                 opt_p,
13753                 opt_t,
13754                 opt_u,
13755                 opt_d
13756         );
13757         INT_ON;
13758
13759         if ((uintptr_t)r == 1 && errno == EINTR) {
13760                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13761                  * Correct behavior is to not exit "read"
13762                  */
13763                 if (pending_sig == 0)
13764                         goto again;
13765         }
13766
13767         if ((uintptr_t)r > 1)
13768                 ash_msg_and_raise_error(r);
13769
13770         return (uintptr_t)r;
13771 }
13772
13773 static int FAST_FUNC
13774 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13775 {
13776         static const char permuser[3] ALIGN1 = "ogu";
13777
13778         mode_t mask;
13779         int symbolic_mode = 0;
13780
13781         while (nextopt("S") != '\0') {
13782                 symbolic_mode = 1;
13783         }
13784
13785         INT_OFF;
13786         mask = umask(0);
13787         umask(mask);
13788         INT_ON;
13789
13790         if (*argptr == NULL) {
13791                 if (symbolic_mode) {
13792                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13793                         char *p = buf;
13794                         int i;
13795
13796                         i = 2;
13797                         for (;;) {
13798                                 *p++ = ',';
13799                                 *p++ = permuser[i];
13800                                 *p++ = '=';
13801                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13802                                 if (!(mask & 0400)) *p++ = 'r';
13803                                 if (!(mask & 0200)) *p++ = 'w';
13804                                 if (!(mask & 0100)) *p++ = 'x';
13805                                 mask <<= 3;
13806                                 if (--i < 0)
13807                                         break;
13808                         }
13809                         *p = '\0';
13810                         puts(buf + 1);
13811                 } else {
13812                         out1fmt("%04o\n", mask);
13813                 }
13814         } else {
13815                 char *modestr = *argptr;
13816                 /* numeric umasks are taken as-is */
13817                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13818                 if (!isdigit(modestr[0]))
13819                         mask ^= 0777;
13820                 mask = bb_parse_mode(modestr, mask);
13821                 if ((unsigned)mask > 0777) {
13822                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13823                 }
13824                 if (!isdigit(modestr[0]))
13825                         mask ^= 0777;
13826                 umask(mask);
13827         }
13828         return 0;
13829 }
13830
13831 static int FAST_FUNC
13832 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13833 {
13834         return shell_builtin_ulimit(argv);
13835 }
13836
13837 /* ============ main() and helpers */
13838
13839 /*
13840  * Called to exit the shell.
13841  */
13842 static void
13843 exitshell(void)
13844 {
13845         struct jmploc loc;
13846         char *p;
13847         int status;
13848
13849 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13850         save_history(line_input_state);
13851 #endif
13852         status = exitstatus;
13853         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13854         if (setjmp(loc.loc)) {
13855                 if (exception_type == EXEXIT)
13856                         status = exitstatus;
13857                 goto out;
13858         }
13859         exception_handler = &loc;
13860         p = trap[0];
13861         if (p) {
13862                 trap[0] = NULL;
13863                 evalskip = 0;
13864                 evalstring(p, 0);
13865                 /*free(p); - we'll exit soon */
13866         }
13867  out:
13868         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13869          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13870          */
13871         setjobctl(0);
13872         flush_stdout_stderr();
13873         _exit(status);
13874         /* NOTREACHED */
13875 }
13876
13877 /* Don't inline: conserve stack of caller from having our locals too */
13878 static NOINLINE void
13879 init(void)
13880 {
13881         /* we will never free this */
13882         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13883         basepf.linno = 1;
13884
13885         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13886         setsignal(SIGCHLD);
13887
13888         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13889          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13890          */
13891         signal(SIGHUP, SIG_DFL);
13892
13893         {
13894                 char **envp;
13895                 const char *p;
13896
13897                 initvar();
13898                 for (envp = environ; envp && *envp; envp++) {
13899 /* Used to have
13900  *                      p = endofname(*envp);
13901  *                      if (p != *envp && *p == '=') {
13902  * here to weed out badly-named variables, but this breaks
13903  * scenarios where people do want them passed to children:
13904  * import os
13905  * os.environ["test-test"]="test"
13906  * if os.fork() == 0:
13907  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13908  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13909  */
13910                         if (strchr(*envp, '=')) {
13911                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13912                         }
13913                 }
13914
13915                 setvareq((char*)defoptindvar, VTEXTFIXED);
13916
13917                 setvar0("PPID", utoa(getppid()));
13918 #if BASH_SHLVL_VAR
13919                 p = lookupvar("SHLVL");
13920                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13921 #endif
13922 #if BASH_HOSTNAME_VAR
13923                 if (!lookupvar("HOSTNAME")) {
13924                         struct utsname uts;
13925                         uname(&uts);
13926                         setvar0("HOSTNAME", uts.nodename);
13927                 }
13928 #endif
13929                 p = lookupvar("PWD");
13930                 if (p) {
13931                         struct stat st1, st2;
13932                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13933                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13934                         ) {
13935                                 p = NULL;
13936                         }
13937                 }
13938                 setpwd(p, 0);
13939         }
13940 }
13941
13942
13943 //usage:#define ash_trivial_usage
13944 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13945 //usage:#define ash_full_usage "\n\n"
13946 //usage:        "Unix shell interpreter"
13947
13948 /*
13949  * Process the shell command line arguments.
13950  */
13951 static int
13952 procargs(char **argv)
13953 {
13954         int i;
13955         const char *xminusc;
13956         char **xargv;
13957         int login_sh;
13958
13959         xargv = argv;
13960         login_sh = xargv[0] && xargv[0][0] == '-';
13961         arg0 = xargv[0];
13962         /* if (xargv[0]) - mmm, this is always true! */
13963                 xargv++;
13964         for (i = 0; i < NOPTS; i++)
13965                 optlist[i] = 2;
13966         argptr = xargv;
13967         if (options(/*cmdline:*/ 1, &login_sh)) {
13968                 /* it already printed err message */
13969                 raise_exception(EXERROR);
13970         }
13971         xargv = argptr;
13972         xminusc = minusc;
13973         if (*xargv == NULL) {
13974                 if (xminusc)
13975                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13976                 sflag = 1;
13977         }
13978         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13979                 iflag = 1;
13980         if (mflag == 2)
13981                 mflag = iflag;
13982         for (i = 0; i < NOPTS; i++)
13983                 if (optlist[i] == 2)
13984                         optlist[i] = 0;
13985 #if DEBUG == 2
13986         debug = 1;
13987 #endif
13988         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13989         if (xminusc) {
13990                 minusc = *xargv++;
13991                 if (*xargv)
13992                         goto setarg0;
13993         } else if (!sflag) {
13994                 setinputfile(*xargv, 0);
13995  setarg0:
13996                 arg0 = *xargv++;
13997                 commandname = arg0;
13998         }
13999
14000         shellparam.p = xargv;
14001 #if ENABLE_ASH_GETOPTS
14002         shellparam.optind = 1;
14003         shellparam.optoff = -1;
14004 #endif
14005         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14006         while (*xargv) {
14007                 shellparam.nparam++;
14008                 xargv++;
14009         }
14010         optschanged();
14011
14012         return login_sh;
14013 }
14014
14015 /*
14016  * Read /etc/profile, ~/.profile, $ENV.
14017  */
14018 static void
14019 read_profile(const char *name)
14020 {
14021         name = expandstr(name, DQSYNTAX);
14022         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14023                 return;
14024         cmdloop(0);
14025         popfile();
14026 }
14027
14028 /*
14029  * This routine is called when an error or an interrupt occurs in an
14030  * interactive shell and control is returned to the main command loop.
14031  * (In dash, this function is auto-generated by build machinery).
14032  */
14033 static void
14034 reset(void)
14035 {
14036         /* from eval.c: */
14037         evalskip = 0;
14038         loopnest = 0;
14039
14040         /* from expand.c: */
14041         ifsfree();
14042
14043         /* from input.c: */
14044         g_parsefile->left_in_buffer = 0;
14045         g_parsefile->left_in_line = 0;      /* clear input buffer */
14046         popallfiles();
14047
14048         /* from redir.c: */
14049         unwindredir(NULL);
14050
14051         /* from var.c: */
14052         unwindlocalvars(NULL);
14053 }
14054
14055 #if PROFILE
14056 static short profile_buf[16384];
14057 extern int etext();
14058 #endif
14059
14060 /*
14061  * Main routine.  We initialize things, parse the arguments, execute
14062  * profiles if we're a login shell, and then call cmdloop to execute
14063  * commands.  The setjmp call sets up the location to jump to when an
14064  * exception occurs.  When an exception occurs the variable "state"
14065  * is used to figure out how far we had gotten.
14066  */
14067 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14068 int ash_main(int argc UNUSED_PARAM, char **argv)
14069 {
14070         volatile smallint state;
14071         struct jmploc jmploc;
14072         struct stackmark smark;
14073         int login_sh;
14074
14075         /* Initialize global data */
14076         INIT_G_misc();
14077         INIT_G_memstack();
14078         INIT_G_var();
14079 #if ENABLE_ASH_ALIAS
14080         INIT_G_alias();
14081 #endif
14082         INIT_G_cmdtable();
14083
14084 #if PROFILE
14085         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14086 #endif
14087
14088 #if ENABLE_FEATURE_EDITING
14089         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14090 #endif
14091         state = 0;
14092         if (setjmp(jmploc.loc)) {
14093                 smallint e;
14094                 smallint s;
14095
14096                 reset();
14097
14098                 e = exception_type;
14099                 s = state;
14100                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14101                         exitshell();
14102                 }
14103                 if (e == EXINT) {
14104                         newline_and_flush(stderr);
14105                 }
14106
14107                 popstackmark(&smark);
14108                 FORCE_INT_ON; /* enable interrupts */
14109                 if (s == 1)
14110                         goto state1;
14111                 if (s == 2)
14112                         goto state2;
14113                 if (s == 3)
14114                         goto state3;
14115                 goto state4;
14116         }
14117         exception_handler = &jmploc;
14118         rootpid = getpid();
14119
14120         init();
14121         setstackmark(&smark);
14122         login_sh = procargs(argv);
14123 #if DEBUG
14124         TRACE(("Shell args: "));
14125         trace_puts_args(argv);
14126 #endif
14127
14128         if (login_sh) {
14129                 const char *hp;
14130
14131                 state = 1;
14132                 read_profile("/etc/profile");
14133  state1:
14134                 state = 2;
14135                 hp = lookupvar("HOME");
14136                 if (hp)
14137                         read_profile("$HOME/.profile");
14138         }
14139  state2:
14140         state = 3;
14141         if (
14142 #ifndef linux
14143          getuid() == geteuid() && getgid() == getegid() &&
14144 #endif
14145          iflag
14146         ) {
14147                 const char *shinit = lookupvar("ENV");
14148                 if (shinit != NULL && *shinit != '\0')
14149                         read_profile(shinit);
14150         }
14151         popstackmark(&smark);
14152  state3:
14153         state = 4;
14154         if (minusc) {
14155                 /* evalstring pushes parsefile stack.
14156                  * Ensure we don't falsely claim that 0 (stdin)
14157                  * is one of stacked source fds.
14158                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14159                 // if (!sflag) g_parsefile->pf_fd = -1;
14160                 // ^^ not necessary since now we special-case fd 0
14161                 // in save_fd_on_redirect()
14162                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14163         }
14164
14165         if (sflag || minusc == NULL) {
14166 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14167                 if (iflag) {
14168                         const char *hp = lookupvar("HISTFILE");
14169                         if (!hp) {
14170                                 hp = lookupvar("HOME");
14171                                 if (hp) {
14172                                         INT_OFF;
14173                                         hp = concat_path_file(hp, ".ash_history");
14174                                         setvar0("HISTFILE", hp);
14175                                         free((char*)hp);
14176                                         INT_ON;
14177                                         hp = lookupvar("HISTFILE");
14178                                 }
14179                         }
14180                         if (hp)
14181                                 line_input_state->hist_file = hp;
14182 # if ENABLE_FEATURE_SH_HISTFILESIZE
14183                         hp = lookupvar("HISTFILESIZE");
14184                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14185 # endif
14186                 }
14187 #endif
14188  state4: /* XXX ??? - why isn't this before the "if" statement */
14189                 cmdloop(1);
14190         }
14191 #if PROFILE
14192         monitor(0);
14193 #endif
14194 #ifdef GPROF
14195         {
14196                 extern void _mcleanup(void);
14197                 _mcleanup();
14198         }
14199 #endif
14200         TRACE(("End of main reached\n"));
14201         exitshell();
14202         /* NOTREACHED */
14203 }
14204
14205
14206 /*-
14207  * Copyright (c) 1989, 1991, 1993, 1994
14208  *      The Regents of the University of California.  All rights reserved.
14209  *
14210  * This code is derived from software contributed to Berkeley by
14211  * Kenneth Almquist.
14212  *
14213  * Redistribution and use in source and binary forms, with or without
14214  * modification, are permitted provided that the following conditions
14215  * are met:
14216  * 1. Redistributions of source code must retain the above copyright
14217  *    notice, this list of conditions and the following disclaimer.
14218  * 2. Redistributions in binary form must reproduce the above copyright
14219  *    notice, this list of conditions and the following disclaimer in the
14220  *    documentation and/or other materials provided with the distribution.
14221  * 3. Neither the name of the University nor the names of its contributors
14222  *    may be used to endorse or promote products derived from this software
14223  *    without specific prior written permission.
14224  *
14225  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14226  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14227  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14228  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14229  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14230  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14231  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14232  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14233  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14234  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14235  * SUCH DAMAGE.
14236  */