8fb32c1ae682a435f55c75927a96df9da9feb383
[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) < 0 && 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_QPAT        0x20    /* pattern in quoted parameter expansion */
5892 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5893 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5894 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5895 /*
5896  * rmescape() flags
5897  */
5898 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5899 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5900 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5901 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5902
5903 /* Add CTLESC when necessary. */
5904 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5905 /* Do not skip NUL characters. */
5906 #define QUOTES_KEEPNUL EXP_TILDE
5907
5908 /*
5909  * Structure specifying which parts of the string should be searched
5910  * for IFS characters.
5911  */
5912 struct ifsregion {
5913         struct ifsregion *next; /* next region in list */
5914         int begoff;             /* offset of start of region */
5915         int endoff;             /* offset of end of region */
5916         int nulonly;            /* search for nul bytes only */
5917 };
5918
5919 struct arglist {
5920         struct strlist *list;
5921         struct strlist **lastp;
5922 };
5923
5924 /* output of current string */
5925 static char *expdest;
5926 /* list of back quote expressions */
5927 static struct nodelist *argbackq;
5928 /* first struct in list of ifs regions */
5929 static struct ifsregion ifsfirst;
5930 /* last struct in list */
5931 static struct ifsregion *ifslastp;
5932 /* holds expanded arg list */
5933 static struct arglist exparg;
5934
5935 /*
5936  * Our own itoa().
5937  * cvtnum() is used even if math support is off (to prepare $? values and such).
5938  */
5939 static int
5940 cvtnum(arith_t num)
5941 {
5942         int len;
5943
5944         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5945         len = sizeof(arith_t) * 3;
5946         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5947         if (sizeof(arith_t) < 4) len += 2;
5948
5949         expdest = makestrspace(len, expdest);
5950         len = fmtstr(expdest, len, ARITH_FMT, num);
5951         STADJUST(len, expdest);
5952         return len;
5953 }
5954
5955 /*
5956  * Break the argument string into pieces based upon IFS and add the
5957  * strings to the argument list.  The regions of the string to be
5958  * searched for IFS characters have been stored by recordregion.
5959  */
5960 static void
5961 ifsbreakup(char *string, struct arglist *arglist)
5962 {
5963         struct ifsregion *ifsp;
5964         struct strlist *sp;
5965         char *start;
5966         char *p;
5967         char *q;
5968         const char *ifs, *realifs;
5969         int ifsspc;
5970         int nulonly;
5971
5972         start = string;
5973         if (ifslastp != NULL) {
5974                 ifsspc = 0;
5975                 nulonly = 0;
5976                 realifs = ifsset() ? ifsval() : defifs;
5977                 ifsp = &ifsfirst;
5978                 do {
5979                         p = string + ifsp->begoff;
5980                         nulonly = ifsp->nulonly;
5981                         ifs = nulonly ? nullstr : realifs;
5982                         ifsspc = 0;
5983                         while (p < string + ifsp->endoff) {
5984                                 q = p;
5985                                 if ((unsigned char)*p == CTLESC)
5986                                         p++;
5987                                 if (!strchr(ifs, *p)) {
5988                                         p++;
5989                                         continue;
5990                                 }
5991                                 if (!nulonly)
5992                                         ifsspc = (strchr(defifs, *p) != NULL);
5993                                 /* Ignore IFS whitespace at start */
5994                                 if (q == start && ifsspc) {
5995                                         p++;
5996                                         start = p;
5997                                         continue;
5998                                 }
5999                                 *q = '\0';
6000                                 sp = stzalloc(sizeof(*sp));
6001                                 sp->text = start;
6002                                 *arglist->lastp = sp;
6003                                 arglist->lastp = &sp->next;
6004                                 p++;
6005                                 if (!nulonly) {
6006                                         for (;;) {
6007                                                 if (p >= string + ifsp->endoff) {
6008                                                         break;
6009                                                 }
6010                                                 q = p;
6011                                                 if ((unsigned char)*p == CTLESC)
6012                                                         p++;
6013                                                 if (strchr(ifs, *p) == NULL) {
6014                                                         p = q;
6015                                                         break;
6016                                                 }
6017                                                 if (strchr(defifs, *p) == NULL) {
6018                                                         if (ifsspc) {
6019                                                                 p++;
6020                                                                 ifsspc = 0;
6021                                                         } else {
6022                                                                 p = q;
6023                                                                 break;
6024                                                         }
6025                                                 } else
6026                                                         p++;
6027                                         }
6028                                 }
6029                                 start = p;
6030                         } /* while */
6031                         ifsp = ifsp->next;
6032                 } while (ifsp != NULL);
6033                 if (nulonly)
6034                         goto add;
6035         }
6036
6037         if (!*start)
6038                 return;
6039
6040  add:
6041         sp = stzalloc(sizeof(*sp));
6042         sp->text = start;
6043         *arglist->lastp = sp;
6044         arglist->lastp = &sp->next;
6045 }
6046
6047 static void
6048 ifsfree(void)
6049 {
6050         struct ifsregion *p = ifsfirst.next;
6051
6052         if (!p)
6053                 goto out;
6054
6055         INT_OFF;
6056         do {
6057                 struct ifsregion *ifsp;
6058                 ifsp = p->next;
6059                 free(p);
6060                 p = ifsp;
6061         } while (p);
6062         ifsfirst.next = NULL;
6063         INT_ON;
6064  out:
6065         ifslastp = NULL;
6066 }
6067
6068 static size_t
6069 esclen(const char *start, const char *p)
6070 {
6071         size_t esc = 0;
6072
6073         while (p > start && (unsigned char)*--p == CTLESC) {
6074                 esc++;
6075         }
6076         return esc;
6077 }
6078
6079 /*
6080  * Remove any CTLESC characters from a string.
6081  */
6082 #if !BASH_PATTERN_SUBST
6083 #define rmescapes(str, flag, slash_position) \
6084         rmescapes(str, flag)
6085 #endif
6086 static char *
6087 rmescapes(char *str, int flag, int *slash_position)
6088 {
6089         static const char qchars[] ALIGN1 = {
6090                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6091
6092         char *p, *q, *r;
6093         unsigned inquotes;
6094         unsigned protect_against_glob;
6095         unsigned globbing;
6096
6097         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6098         if (!p)
6099                 return str;
6100
6101         q = p;
6102         r = str;
6103         if (flag & RMESCAPE_ALLOC) {
6104                 size_t len = p - str;
6105                 size_t fulllen = len + strlen(p) + 1;
6106
6107                 if (flag & RMESCAPE_GROW) {
6108                         int strloc = str - (char *)stackblock();
6109                         r = makestrspace(fulllen, expdest);
6110                         /* p and str may be invalidated by makestrspace */
6111                         str = (char *)stackblock() + strloc;
6112                         p = str + len;
6113                 } else if (flag & RMESCAPE_HEAP) {
6114                         r = ckmalloc(fulllen);
6115                 } else {
6116                         r = stalloc(fulllen);
6117                 }
6118                 q = r;
6119                 if (len > 0) {
6120                         q = (char *)mempcpy(q, str, len);
6121                 }
6122         }
6123
6124         inquotes = 0;
6125         globbing = flag & RMESCAPE_GLOB;
6126         protect_against_glob = globbing;
6127         while (*p) {
6128                 if ((unsigned char)*p == CTLQUOTEMARK) {
6129 // Note: both inquotes and protect_against_glob only affect whether
6130 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6131                         inquotes = ~inquotes;
6132                         p++;
6133                         protect_against_glob = globbing;
6134                         continue;
6135                 }
6136                 if ((unsigned char)*p == CTLESC) {
6137                         p++;
6138 #if DEBUG
6139                         if (*p == '\0')
6140                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6141 #endif
6142                         if (protect_against_glob) {
6143                                 /*
6144                                  * We used to trust glob() and fnmatch() to eat
6145                                  * superfluous escapes (\z where z has no
6146                                  * special meaning anyway). But this causes
6147                                  * bugs such as string of one greek letter rho
6148                                  * (unicode-encoded as two bytes "cf,81")
6149                                  * getting encoded as "cf,CTLESC,81"
6150                                  * and here, converted to "cf,\,81" -
6151                                  * which does not go well with some flavors
6152                                  * of fnmatch() in unicode locales
6153                                  * (for example, glibc <= 2.22).
6154                                  *
6155                                  * Lets add "\" only on the chars which need it.
6156                                  * Testcases for less obvious chars are shown.
6157                                  */
6158                                 if (*p == '*'
6159                                  || *p == '?'
6160                                  || *p == '['
6161                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6162                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6163                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6164                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6165                                 /* Some libc support [^negate], that's why "^" also needs love */
6166                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6167                                 ) {
6168                                         *q++ = '\\';
6169                                 }
6170                         }
6171                 } else if (*p == '\\' && !inquotes) {
6172                         /* naked back slash */
6173                         protect_against_glob = 0;
6174                         goto copy;
6175                 }
6176 #if BASH_PATTERN_SUBST
6177                 else if (slash_position && p == str + *slash_position) {
6178                         /* stop handling globbing */
6179                         globbing = 0;
6180                         *slash_position = q - r;
6181                         slash_position = NULL;
6182                 }
6183 #endif
6184                 protect_against_glob = globbing;
6185  copy:
6186                 *q++ = *p++;
6187         }
6188         *q = '\0';
6189         if (flag & RMESCAPE_GROW) {
6190                 expdest = r;
6191                 STADJUST(q - r + 1, expdest);
6192         }
6193         return r;
6194 }
6195 #define pmatch(a, b) !fnmatch((a), (b), 0)
6196
6197 /*
6198  * Prepare a pattern for a expmeta (internal glob(3)) call.
6199  *
6200  * Returns an stalloced string.
6201  */
6202 static char *
6203 preglob(const char *pattern, int flag)
6204 {
6205         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6206 }
6207
6208 /*
6209  * Put a string on the stack.
6210  */
6211 static void
6212 memtodest(const char *p, size_t len, int syntax, int quotes)
6213 {
6214         char *q;
6215
6216         if (!len)
6217                 return;
6218
6219         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6220
6221         do {
6222                 unsigned char c = *p++;
6223                 if (c) {
6224                         if (quotes & QUOTES_ESC) {
6225                                 int n = SIT(c, syntax);
6226                                 if (n == CCTL
6227                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6228                                      && n == CBACK
6229                                     )
6230                                 ) {
6231                                         USTPUTC(CTLESC, q);
6232                                 }
6233                         }
6234                 } else if (!(quotes & QUOTES_KEEPNUL))
6235                         continue;
6236                 USTPUTC(c, q);
6237         } while (--len);
6238
6239         expdest = q;
6240 }
6241
6242 static size_t
6243 strtodest(const char *p, int syntax, int quotes)
6244 {
6245         size_t len = strlen(p);
6246         memtodest(p, len, syntax, quotes);
6247         return len;
6248 }
6249
6250 /*
6251  * Record the fact that we have to scan this region of the
6252  * string for IFS characters.
6253  */
6254 static void
6255 recordregion(int start, int end, int nulonly)
6256 {
6257         struct ifsregion *ifsp;
6258
6259         if (ifslastp == NULL) {
6260                 ifsp = &ifsfirst;
6261         } else {
6262                 INT_OFF;
6263                 ifsp = ckzalloc(sizeof(*ifsp));
6264                 /*ifsp->next = NULL; - ckzalloc did it */
6265                 ifslastp->next = ifsp;
6266                 INT_ON;
6267         }
6268         ifslastp = ifsp;
6269         ifslastp->begoff = start;
6270         ifslastp->endoff = end;
6271         ifslastp->nulonly = nulonly;
6272 }
6273
6274 static void
6275 removerecordregions(int endoff)
6276 {
6277         if (ifslastp == NULL)
6278                 return;
6279
6280         if (ifsfirst.endoff > endoff) {
6281                 while (ifsfirst.next) {
6282                         struct ifsregion *ifsp;
6283                         INT_OFF;
6284                         ifsp = ifsfirst.next->next;
6285                         free(ifsfirst.next);
6286                         ifsfirst.next = ifsp;
6287                         INT_ON;
6288                 }
6289                 if (ifsfirst.begoff > endoff) {
6290                         ifslastp = NULL;
6291                 } else {
6292                         ifslastp = &ifsfirst;
6293                         ifsfirst.endoff = endoff;
6294                 }
6295                 return;
6296         }
6297
6298         ifslastp = &ifsfirst;
6299         while (ifslastp->next && ifslastp->next->begoff < endoff)
6300                 ifslastp = ifslastp->next;
6301         while (ifslastp->next) {
6302                 struct ifsregion *ifsp;
6303                 INT_OFF;
6304                 ifsp = ifslastp->next->next;
6305                 free(ifslastp->next);
6306                 ifslastp->next = ifsp;
6307                 INT_ON;
6308         }
6309         if (ifslastp->endoff > endoff)
6310                 ifslastp->endoff = endoff;
6311 }
6312
6313 static char *
6314 exptilde(char *startp, char *p, int flags)
6315 {
6316         unsigned char c;
6317         char *name;
6318         struct passwd *pw;
6319         const char *home;
6320         int quotes = flags & QUOTES_ESC;
6321
6322         name = p + 1;
6323
6324         while ((c = *++p) != '\0') {
6325                 switch (c) {
6326                 case CTLESC:
6327                         return startp;
6328                 case CTLQUOTEMARK:
6329                         return startp;
6330                 case ':':
6331                         if (flags & EXP_VARTILDE)
6332                                 goto done;
6333                         break;
6334                 case '/':
6335                 case CTLENDVAR:
6336                         goto done;
6337                 }
6338         }
6339  done:
6340         *p = '\0';
6341         if (*name == '\0') {
6342                 home = lookupvar("HOME");
6343         } else {
6344                 pw = getpwnam(name);
6345                 if (pw == NULL)
6346                         goto lose;
6347                 home = pw->pw_dir;
6348         }
6349         if (!home || !*home)
6350                 goto lose;
6351         *p = c;
6352         strtodest(home, SQSYNTAX, quotes);
6353         return p;
6354  lose:
6355         *p = c;
6356         return startp;
6357 }
6358
6359 /*
6360  * Execute a command inside back quotes.  If it's a builtin command, we
6361  * want to save its output in a block obtained from malloc.  Otherwise
6362  * we fork off a subprocess and get the output of the command via a pipe.
6363  * Should be called with interrupts off.
6364  */
6365 struct backcmd {                /* result of evalbackcmd */
6366         int fd;                 /* file descriptor to read from */
6367         int nleft;              /* number of chars in buffer */
6368         char *buf;              /* buffer */
6369         struct job *jp;         /* job structure for command */
6370 };
6371
6372 /* These forward decls are needed to use "eval" code for backticks handling: */
6373 /* flags in argument to evaltree */
6374 #define EV_EXIT    01           /* exit after evaluating tree */
6375 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6376 static int evaltree(union node *, int);
6377
6378 /* An evaltree() which is known to never return.
6379  * Used to use an alias:
6380  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6381  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6382  */
6383 static ALWAYS_INLINE NORETURN void
6384 evaltreenr(union node *n, int flags)
6385 {
6386         evaltree(n, flags);
6387         bb_unreachable(abort());
6388         /* NOTREACHED */
6389 }
6390
6391 static void FAST_FUNC
6392 evalbackcmd(union node *n, struct backcmd *result)
6393 {
6394         int pip[2];
6395         struct job *jp;
6396
6397         result->fd = -1;
6398         result->buf = NULL;
6399         result->nleft = 0;
6400         result->jp = NULL;
6401         if (n == NULL) {
6402                 goto out;
6403         }
6404
6405         if (pipe(pip) < 0)
6406                 ash_msg_and_raise_perror("can't create pipe");
6407         jp = makejob(/*n,*/ 1);
6408         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6409                 /* child */
6410                 FORCE_INT_ON;
6411                 close(pip[0]);
6412                 if (pip[1] != 1) {
6413                         /*close(1);*/
6414                         dup2_or_raise(pip[1], 1);
6415                         close(pip[1]);
6416                 }
6417 /* TODO: eflag clearing makes the following not abort:
6418  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6419  * which is what bash does (unless it is in POSIX mode).
6420  * dash deleted "eflag = 0" line in the commit
6421  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6422  *  [EVAL] Don't clear eflag in evalbackcmd
6423  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6424  */
6425                 eflag = 0;
6426                 ifsfree();
6427                 evaltreenr(n, EV_EXIT);
6428                 /* NOTREACHED */
6429         }
6430         /* parent */
6431         close(pip[1]);
6432         result->fd = pip[0];
6433         result->jp = jp;
6434
6435  out:
6436         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6437                 result->fd, result->buf, result->nleft, result->jp));
6438 }
6439
6440 /*
6441  * Expand stuff in backwards quotes.
6442  */
6443 static void
6444 expbackq(union node *cmd, int flag)
6445 {
6446         struct backcmd in;
6447         int i;
6448         char buf[128];
6449         char *p;
6450         char *dest;
6451         int startloc;
6452         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6453         struct stackmark smark;
6454
6455         INT_OFF;
6456         startloc = expdest - (char *)stackblock();
6457         pushstackmark(&smark, startloc);
6458         evalbackcmd(cmd, &in);
6459         popstackmark(&smark);
6460
6461         p = in.buf;
6462         i = in.nleft;
6463         if (i == 0)
6464                 goto read;
6465         for (;;) {
6466                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6467  read:
6468                 if (in.fd < 0)
6469                         break;
6470                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6471                 TRACE(("expbackq: read returns %d\n", i));
6472                 if (i <= 0)
6473                         break;
6474                 p = buf;
6475         }
6476
6477         free(in.buf);
6478         if (in.fd >= 0) {
6479                 close(in.fd);
6480                 back_exitstatus = waitforjob(in.jp);
6481         }
6482         INT_ON;
6483
6484         /* Eat all trailing newlines */
6485         dest = expdest;
6486         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6487                 STUNPUTC(dest);
6488         expdest = dest;
6489
6490         if (!(flag & EXP_QUOTED))
6491                 recordregion(startloc, dest - (char *)stackblock(), 0);
6492         TRACE(("evalbackq: size:%d:'%.*s'\n",
6493                 (int)((dest - (char *)stackblock()) - startloc),
6494                 (int)((dest - (char *)stackblock()) - startloc),
6495                 stackblock() + startloc));
6496 }
6497
6498 #if ENABLE_FEATURE_SH_MATH
6499 /*
6500  * Expand arithmetic expression.  Backup to start of expression,
6501  * evaluate, place result in (backed up) result, adjust string position.
6502  */
6503 static void
6504 expari(int flag)
6505 {
6506         char *p, *start;
6507         int begoff;
6508         int len;
6509
6510         /* ifsfree(); */
6511
6512         /*
6513          * This routine is slightly over-complicated for
6514          * efficiency.  Next we scan backwards looking for the
6515          * start of arithmetic.
6516          */
6517         start = stackblock();
6518         p = expdest - 1;
6519         *p = '\0';
6520         p--;
6521         while (1) {
6522                 int esc;
6523
6524                 while ((unsigned char)*p != CTLARI) {
6525                         p--;
6526 #if DEBUG
6527                         if (p < start) {
6528                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6529                         }
6530 #endif
6531                 }
6532
6533                 esc = esclen(start, p);
6534                 if (!(esc % 2)) {
6535                         break;
6536                 }
6537
6538                 p -= esc + 1;
6539         }
6540
6541         begoff = p - start;
6542
6543         removerecordregions(begoff);
6544
6545         expdest = p;
6546
6547         if (flag & QUOTES_ESC)
6548                 rmescapes(p + 1, 0, NULL);
6549
6550         len = cvtnum(ash_arith(p + 1));
6551
6552         if (!(flag & EXP_QUOTED))
6553                 recordregion(begoff, begoff + len, 0);
6554 }
6555 #endif
6556
6557 /* argstr needs it */
6558 static char *evalvar(char *p, int flags);
6559
6560 /*
6561  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6562  * characters to allow for further processing.  Otherwise treat
6563  * $@ like $* since no splitting will be performed.
6564  */
6565 static void
6566 argstr(char *p, int flags)
6567 {
6568         static const char spclchars[] ALIGN1 = {
6569                 '=',
6570                 ':',
6571                 CTLQUOTEMARK,
6572                 CTLENDVAR,
6573                 CTLESC,
6574                 CTLVAR,
6575                 CTLBACKQ,
6576 #if ENABLE_FEATURE_SH_MATH
6577                 CTLENDARI,
6578 #endif
6579                 '\0'
6580         };
6581         const char *reject = spclchars;
6582         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6583         int inquotes;
6584         size_t length;
6585         int startloc;
6586
6587         if (!(flags & EXP_VARTILDE)) {
6588                 reject += 2;
6589         } else if (flags & EXP_VARTILDE2) {
6590                 reject++;
6591         }
6592         inquotes = 0;
6593         length = 0;
6594         if (flags & EXP_TILDE) {
6595                 char *q;
6596
6597                 flags &= ~EXP_TILDE;
6598  tilde:
6599                 q = p;
6600                 if (*q == '~')
6601                         p = exptilde(p, q, flags);
6602         }
6603  start:
6604         startloc = expdest - (char *)stackblock();
6605         for (;;) {
6606                 unsigned char c;
6607
6608                 length += strcspn(p + length, reject);
6609                 c = p[length];
6610                 if (c) {
6611                         if (!(c & 0x80)
6612                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6613                         ) {
6614                                 /* c == '=' || c == ':' || c == CTLENDARI */
6615                                 length++;
6616                         }
6617                 }
6618                 if (length > 0) {
6619                         int newloc;
6620                         expdest = stack_nputstr(p, length, expdest);
6621                         newloc = expdest - (char *)stackblock();
6622                         if (breakall && !inquotes && newloc > startloc) {
6623                                 recordregion(startloc, newloc, 0);
6624                         }
6625                         startloc = newloc;
6626                 }
6627                 p += length + 1;
6628                 length = 0;
6629
6630                 switch (c) {
6631                 case '\0':
6632                         goto breakloop;
6633                 case '=':
6634                         if (flags & EXP_VARTILDE2) {
6635                                 p--;
6636                                 continue;
6637                         }
6638                         flags |= EXP_VARTILDE2;
6639                         reject++;
6640                         /* fall through */
6641                 case ':':
6642                         /*
6643                          * sort of a hack - expand tildes in variable
6644                          * assignments (after the first '=' and after ':'s).
6645                          */
6646                         if (*--p == '~') {
6647                                 goto tilde;
6648                         }
6649                         continue;
6650                 }
6651
6652                 switch (c) {
6653                 case CTLENDVAR: /* ??? */
6654                         goto breakloop;
6655                 case CTLQUOTEMARK:
6656                         inquotes ^= EXP_QUOTED;
6657                         /* "$@" syntax adherence hack */
6658                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6659                                 p = evalvar(p + 1, flags | inquotes) + 1;
6660                                 goto start;
6661                         }
6662  addquote:
6663                         if (flags & QUOTES_ESC) {
6664                                 p--;
6665                                 length++;
6666                                 startloc++;
6667                         }
6668                         break;
6669                 case CTLESC:
6670                         startloc++;
6671                         length++;
6672
6673                         /*
6674                          * Quoted parameter expansion pattern: remove quote
6675                          * unless inside inner quotes or we have a literal
6676                          * backslash.
6677                          */
6678                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6679                             EXP_QPAT && *p != '\\')
6680                                 break;
6681
6682                         goto addquote;
6683                 case CTLVAR:
6684                         TRACE(("argstr: evalvar('%s')\n", p));
6685                         p = evalvar(p, flags | inquotes);
6686                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6687                         goto start;
6688                 case CTLBACKQ:
6689                         expbackq(argbackq->n, flags | inquotes);
6690                         argbackq = argbackq->next;
6691                         goto start;
6692 #if ENABLE_FEATURE_SH_MATH
6693                 case CTLENDARI:
6694                         p--;
6695                         expari(flags | inquotes);
6696                         goto start;
6697 #endif
6698                 }
6699         }
6700  breakloop: ;
6701 }
6702
6703 static char *
6704 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6705                 char *pattern, int quotes, int zero)
6706 {
6707         char *loc, *loc2;
6708         char c;
6709
6710         loc = startp;
6711         loc2 = rmesc;
6712         do {
6713                 int match;
6714                 const char *s = loc2;
6715
6716                 c = *loc2;
6717                 if (zero) {
6718                         *loc2 = '\0';
6719                         s = rmesc;
6720                 }
6721                 match = pmatch(pattern, s);
6722
6723                 *loc2 = c;
6724                 if (match)
6725                         return loc;
6726                 if (quotes && (unsigned char)*loc == CTLESC)
6727                         loc++;
6728                 loc++;
6729                 loc2++;
6730         } while (c);
6731         return NULL;
6732 }
6733
6734 static char *
6735 scanright(char *startp, char *rmesc, char *rmescend,
6736                 char *pattern, int quotes, int match_at_start)
6737 {
6738 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6739         int try2optimize = match_at_start;
6740 #endif
6741         int esc = 0;
6742         char *loc;
6743         char *loc2;
6744
6745         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6746          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6747          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6748          * Logic:
6749          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6750          * and on each iteration they go back two/one char until they reach the beginning.
6751          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6752          */
6753         /* TODO: document in what other circumstances we are called. */
6754
6755         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6756                 int match;
6757                 char c = *loc2;
6758                 const char *s = loc2;
6759                 if (match_at_start) {
6760                         *loc2 = '\0';
6761                         s = rmesc;
6762                 }
6763                 match = pmatch(pattern, s);
6764                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6765                 *loc2 = c;
6766                 if (match)
6767                         return loc;
6768 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6769                 if (try2optimize) {
6770                         /* Maybe we can optimize this:
6771                          * if pattern ends with unescaped *, we can avoid checking
6772                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6773                          * it won't match truncated "raw_value_of_" strings too.
6774                          */
6775                         unsigned plen = strlen(pattern);
6776                         /* Does it end with "*"? */
6777                         if (plen != 0 && pattern[--plen] == '*') {
6778                                 /* "xxxx*" is not escaped */
6779                                 /* "xxx\*" is escaped */
6780                                 /* "xx\\*" is not escaped */
6781                                 /* "x\\\*" is escaped */
6782                                 int slashes = 0;
6783                                 while (plen != 0 && pattern[--plen] == '\\')
6784                                         slashes++;
6785                                 if (!(slashes & 1))
6786                                         break; /* ends with unescaped "*" */
6787                         }
6788                         try2optimize = 0;
6789                 }
6790 #endif
6791                 loc--;
6792                 if (quotes) {
6793                         if (--esc < 0) {
6794                                 esc = esclen(startp, loc);
6795                         }
6796                         if (esc % 2) {
6797                                 esc--;
6798                                 loc--;
6799                         }
6800                 }
6801         }
6802         return NULL;
6803 }
6804
6805 static void varunset(const char *, const char *, const char *, int) NORETURN;
6806 static void
6807 varunset(const char *end, const char *var, const char *umsg, int varflags)
6808 {
6809         const char *msg;
6810         const char *tail;
6811
6812         tail = nullstr;
6813         msg = "parameter not set";
6814         if (umsg) {
6815                 if ((unsigned char)*end == CTLENDVAR) {
6816                         if (varflags & VSNUL)
6817                                 tail = " or null";
6818                 } else {
6819                         msg = umsg;
6820                 }
6821         }
6822         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6823 }
6824
6825 static const char *
6826 subevalvar(char *p, char *varname, int strloc, int subtype,
6827                 int startloc, int varflags, int flag)
6828 {
6829         struct nodelist *saveargbackq = argbackq;
6830         int quotes = flag & QUOTES_ESC;
6831         char *startp;
6832         char *loc;
6833         char *rmesc, *rmescend;
6834         char *str;
6835         int amount, resetloc;
6836         int argstr_flags;
6837         IF_BASH_PATTERN_SUBST(int workloc;)
6838         IF_BASH_PATTERN_SUBST(int slash_pos;)
6839         IF_BASH_PATTERN_SUBST(char *repl;)
6840         int zero;
6841         char *(*scan)(char*, char*, char*, char*, int, int);
6842
6843         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6844         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6845
6846 #if BASH_PATTERN_SUBST
6847         /* For "${v/pattern/repl}", we must find the delimiter _before_
6848          * argstr() call expands possible variable references in pattern:
6849          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6850          */
6851         repl = NULL;
6852         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6853                 /* Find '/' and replace with NUL */
6854                 repl = p;
6855                 for (;;) {
6856                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6857                         if (*repl == '\0') {
6858                                 repl = NULL;
6859                                 break;
6860                         }
6861                         if (*repl == '/') {
6862                                 *repl = '\0';
6863                                 break;
6864                         }
6865                         if ((unsigned char)*repl == CTLESC && repl[1])
6866                                 repl++;
6867                         repl++;
6868                 }
6869         }
6870 #endif
6871         argstr_flags = EXP_TILDE;
6872         if (subtype != VSASSIGN && subtype != VSQUESTION)
6873                 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
6874         argstr(p, argstr_flags);
6875 #if BASH_PATTERN_SUBST
6876         slash_pos = -1;
6877         if (repl) {
6878                 slash_pos = expdest - ((char *)stackblock() + strloc);
6879                 STPUTC('/', expdest);
6880                 argstr(repl + 1, argstr_flags);
6881                 *repl = '/';
6882         }
6883 #endif
6884         STPUTC('\0', expdest);
6885         argbackq = saveargbackq;
6886         startp = (char *)stackblock() + startloc;
6887         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6888
6889         switch (subtype) {
6890         case VSASSIGN:
6891                 setvar0(varname, startp);
6892                 amount = startp - expdest;
6893                 STADJUST(amount, expdest);
6894                 return startp;
6895
6896         case VSQUESTION:
6897                 varunset(p, varname, startp, varflags);
6898                 /* NOTREACHED */
6899
6900 #if BASH_SUBSTR
6901         case VSSUBSTR: {
6902                 int pos, len, orig_len;
6903                 char *colon;
6904
6905                 loc = str = stackblock() + strloc;
6906
6907                 /* Read POS in ${var:POS:LEN} */
6908                 colon = strchr(loc, ':');
6909                 if (colon) *colon = '\0';
6910                 pos = substr_atoi(loc);
6911                 if (colon) *colon = ':';
6912
6913                 /* Read LEN in ${var:POS:LEN} */
6914                 len = str - startp - 1;
6915                 /* *loc != '\0', guaranteed by parser */
6916                 if (quotes) {
6917                         char *ptr;
6918                         /* Adjust the length by the number of escapes */
6919                         for (ptr = startp; ptr < (str - 1); ptr++) {
6920                                 if ((unsigned char)*ptr == CTLESC) {
6921                                         len--;
6922                                         ptr++;
6923                                 }
6924                         }
6925                 }
6926                 orig_len = len;
6927                 if (*loc++ == ':') {
6928                         /* ${var::LEN} */
6929                         len = substr_atoi(loc);
6930                 } else {
6931                         /* Skip POS in ${var:POS:LEN} */
6932                         len = orig_len;
6933                         while (*loc && *loc != ':')
6934                                 loc++;
6935                         if (*loc++ == ':')
6936                                 len = substr_atoi(loc);
6937                 }
6938                 if (pos < 0) {
6939                         /* ${VAR:$((-n)):l} starts n chars from the end */
6940                         pos = orig_len + pos;
6941                 }
6942                 if ((unsigned)pos >= orig_len) {
6943                         /* apart from obvious ${VAR:999999:l},
6944                          * covers ${VAR:$((-9999999)):l} - result is ""
6945                          * (bash compat)
6946                          */
6947                         pos = 0;
6948                         len = 0;
6949                 }
6950                 if (len < 0) {
6951                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6952                         len = (orig_len - pos) + len;
6953                 }
6954                 if ((unsigned)len > (orig_len - pos))
6955                         len = orig_len - pos;
6956
6957                 for (str = startp; pos; str++, pos--) {
6958                         if (quotes && (unsigned char)*str == CTLESC)
6959                                 str++;
6960                 }
6961                 for (loc = startp; len; len--) {
6962                         if (quotes && (unsigned char)*str == CTLESC)
6963                                 *loc++ = *str++;
6964                         *loc++ = *str++;
6965                 }
6966                 *loc = '\0';
6967                 amount = loc - expdest;
6968                 STADJUST(amount, expdest);
6969                 return loc;
6970         }
6971 #endif /* BASH_SUBSTR */
6972         }
6973
6974         resetloc = expdest - (char *)stackblock();
6975
6976 #if BASH_PATTERN_SUBST
6977         repl = NULL;
6978
6979         /* We'll comeback here if we grow the stack while handling
6980          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6981          * stack will need rebasing, and we'll need to remove our work
6982          * areas each time
6983          */
6984  restart:
6985 #endif
6986
6987         amount = expdest - ((char *)stackblock() + resetloc);
6988         STADJUST(-amount, expdest);
6989         startp = (char *)stackblock() + startloc;
6990
6991         rmesc = startp;
6992         rmescend = (char *)stackblock() + strloc;
6993         //bb_error_msg("str7:'%s'", rmescend);
6994         if (quotes) {
6995 //TODO: how to handle slash_pos here if string changes (shortens?)
6996                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6997                 if (rmesc != startp) {
6998                         rmescend = expdest;
6999                         startp = (char *)stackblock() + startloc;
7000                 }
7001         }
7002         rmescend--;
7003         str = (char *)stackblock() + strloc;
7004         /*
7005          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7006          * The result is a_\_z_c (not a\_\_z_c)!
7007          *
7008          * The search pattern and replace string treat backslashes differently!
7009          * "&slash_pos" causes rmescapes() to work differently on the pattern
7010          * and string.  It's only used on the first call.
7011          */
7012         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7013         rmescapes(str, RMESCAPE_GLOB,
7014                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7015         );
7016
7017 #if BASH_PATTERN_SUBST
7018         workloc = expdest - (char *)stackblock();
7019         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7020                 int len;
7021                 char *idx, *end;
7022
7023                 if (!repl) {
7024                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7025                         repl = nullstr;
7026                         if (slash_pos >= 0) {
7027                                 repl = str + slash_pos;
7028                                 *repl++ = '\0';
7029                         }
7030                 }
7031                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7032
7033                 /* If there's no pattern to match, return the expansion unmolested */
7034                 if (str[0] == '\0')
7035                         return NULL;
7036
7037                 len = 0;
7038                 idx = startp;
7039                 end = str - 1;
7040                 while (idx < end) {
7041  try_to_match:
7042                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7043                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7044                         if (!loc) {
7045                                 /* No match, advance */
7046                                 char *restart_detect = stackblock();
7047  skip_matching:
7048                                 STPUTC(*idx, expdest);
7049                                 if (quotes && (unsigned char)*idx == CTLESC) {
7050                                         idx++;
7051                                         len++;
7052                                         STPUTC(*idx, expdest);
7053                                 }
7054                                 if (stackblock() != restart_detect)
7055                                         goto restart;
7056                                 idx++;
7057                                 len++;
7058                                 rmesc++;
7059                                 /* continue; - prone to quadratic behavior, smarter code: */
7060                                 if (idx >= end)
7061                                         break;
7062                                 if (str[0] == '*') {
7063                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7064                                          * it would never match "ong_string" etc, no point in trying.
7065                                          */
7066                                         goto skip_matching;
7067                                 }
7068                                 goto try_to_match;
7069                         }
7070
7071                         if (subtype == VSREPLACEALL) {
7072                                 while (idx < loc) {
7073                                         if (quotes && (unsigned char)*idx == CTLESC)
7074                                                 idx++;
7075                                         idx++;
7076                                         rmesc++;
7077                                 }
7078                         } else {
7079                                 idx = loc;
7080                         }
7081
7082                         //bb_error_msg("repl:'%s'", repl);
7083                         for (loc = (char*)repl; *loc; loc++) {
7084                                 char *restart_detect = stackblock();
7085                                 if (quotes && *loc == '\\') {
7086                                         STPUTC(CTLESC, expdest);
7087                                         len++;
7088                                 }
7089                                 STPUTC(*loc, expdest);
7090                                 if (stackblock() != restart_detect)
7091                                         goto restart;
7092                                 len++;
7093                         }
7094
7095                         if (subtype == VSREPLACE) {
7096                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7097                                 while (*idx) {
7098                                         char *restart_detect = stackblock();
7099                                         STPUTC(*idx, expdest);
7100                                         if (stackblock() != restart_detect)
7101                                                 goto restart;
7102                                         len++;
7103                                         idx++;
7104                                 }
7105                                 break;
7106                         }
7107                 }
7108
7109                 /* We've put the replaced text into a buffer at workloc, now
7110                  * move it to the right place and adjust the stack.
7111                  */
7112                 STPUTC('\0', expdest);
7113                 startp = (char *)stackblock() + startloc;
7114                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7115                 //bb_error_msg("startp:'%s'", startp);
7116                 amount = expdest - (startp + len);
7117                 STADJUST(-amount, expdest);
7118                 return startp;
7119         }
7120 #endif /* BASH_PATTERN_SUBST */
7121
7122         subtype -= VSTRIMRIGHT;
7123 #if DEBUG
7124         if (subtype < 0 || subtype > 7)
7125                 abort();
7126 #endif
7127         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7128         zero = subtype >> 1;
7129         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7130         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7131
7132         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7133         if (loc) {
7134                 if (zero) {
7135                         memmove(startp, loc, str - loc);
7136                         loc = startp + (str - loc) - 1;
7137                 }
7138                 *loc = '\0';
7139                 amount = loc - expdest;
7140                 STADJUST(amount, expdest);
7141         }
7142         return loc;
7143 }
7144
7145 /*
7146  * Add the value of a specialized variable to the stack string.
7147  * name parameter (examples):
7148  * ash -c 'echo $1'      name:'1='
7149  * ash -c 'echo $qwe'    name:'qwe='
7150  * ash -c 'echo $$'      name:'$='
7151  * ash -c 'echo ${$}'    name:'$='
7152  * ash -c 'echo ${$##q}' name:'$=q'
7153  * ash -c 'echo ${#$}'   name:'$='
7154  * note: examples with bad shell syntax:
7155  * ash -c 'echo ${#$1}'  name:'$=1'
7156  * ash -c 'echo ${#1#}'  name:'1=#'
7157  */
7158 static NOINLINE ssize_t
7159 varvalue(char *name, int varflags, int flags, int *quotedp)
7160 {
7161         const char *p;
7162         int num;
7163         int i;
7164         ssize_t len = 0;
7165         int sep;
7166         int quoted = *quotedp;
7167         int subtype = varflags & VSTYPE;
7168         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7169         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7170         int syntax;
7171
7172         sep = (flags & EXP_FULL) << CHAR_BIT;
7173         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7174
7175         switch (*name) {
7176         case '$':
7177                 num = rootpid;
7178                 goto numvar;
7179         case '?':
7180                 num = exitstatus;
7181                 goto numvar;
7182         case '#':
7183                 num = shellparam.nparam;
7184                 goto numvar;
7185         case '!':
7186                 num = backgndpid;
7187                 if (num == 0)
7188                         return -1;
7189  numvar:
7190                 len = cvtnum(num);
7191                 goto check_1char_name;
7192         case '-':
7193                 expdest = makestrspace(NOPTS, expdest);
7194                 for (i = NOPTS - 1; i >= 0; i--) {
7195                         if (optlist[i]) {
7196                                 USTPUTC(optletters(i), expdest);
7197                                 len++;
7198                         }
7199                 }
7200  check_1char_name:
7201 #if 0
7202                 /* handles cases similar to ${#$1} */
7203                 if (name[2] != '\0')
7204                         raise_error_syntax("bad substitution");
7205 #endif
7206                 break;
7207         case '@':
7208                 if (quoted && sep)
7209                         goto param;
7210                 /* fall through */
7211         case '*': {
7212                 char **ap;
7213                 char sepc;
7214
7215                 if (quoted)
7216                         sep = 0;
7217                 sep |= ifsset() ? ifsval()[0] : ' ';
7218  param:
7219                 sepc = sep;
7220                 *quotedp = !sepc;
7221                 ap = shellparam.p;
7222                 if (!ap)
7223                         return -1;
7224                 while ((p = *ap++) != NULL) {
7225                         len += strtodest(p, syntax, quotes);
7226
7227                         if (*ap && sep) {
7228                                 len++;
7229                                 memtodest(&sepc, 1, syntax, quotes);
7230                         }
7231                 }
7232                 break;
7233         } /* case '*' */
7234         case '0':
7235         case '1':
7236         case '2':
7237         case '3':
7238         case '4':
7239         case '5':
7240         case '6':
7241         case '7':
7242         case '8':
7243         case '9':
7244                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7245                 if (num < 0 || num > shellparam.nparam)
7246                         return -1;
7247                 p = num ? shellparam.p[num - 1] : arg0;
7248                 goto value;
7249         default:
7250                 /* NB: name has form "VAR=..." */
7251                 p = lookupvar(name);
7252  value:
7253                 if (!p)
7254                         return -1;
7255
7256                 len = strtodest(p, syntax, quotes);
7257 #if ENABLE_UNICODE_SUPPORT
7258                 if (subtype == VSLENGTH && len > 0) {
7259                         reinit_unicode_for_ash();
7260                         if (unicode_status == UNICODE_ON) {
7261                                 STADJUST(-len, expdest);
7262                                 discard = 0;
7263                                 len = unicode_strlen(p);
7264                         }
7265                 }
7266 #endif
7267                 break;
7268         }
7269
7270         if (discard)
7271                 STADJUST(-len, expdest);
7272         return len;
7273 }
7274
7275 /*
7276  * Expand a variable, and return a pointer to the next character in the
7277  * input string.
7278  */
7279 static char *
7280 evalvar(char *p, int flag)
7281 {
7282         char varflags;
7283         char subtype;
7284         int quoted;
7285         char easy;
7286         char *var;
7287         int patloc;
7288         int startloc;
7289         ssize_t varlen;
7290
7291         varflags = (unsigned char) *p++;
7292         subtype = varflags & VSTYPE;
7293
7294         if (!subtype)
7295                 raise_error_syntax("bad substitution");
7296
7297         quoted = flag & EXP_QUOTED;
7298         var = p;
7299         easy = (!quoted || (*var == '@' && shellparam.nparam));
7300         startloc = expdest - (char *)stackblock();
7301         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7302
7303  again:
7304         varlen = varvalue(var, varflags, flag, &quoted);
7305         if (varflags & VSNUL)
7306                 varlen--;
7307
7308         if (subtype == VSPLUS) {
7309                 varlen = -1 - varlen;
7310                 goto vsplus;
7311         }
7312
7313         if (subtype == VSMINUS) {
7314  vsplus:
7315                 if (varlen < 0) {
7316                         argstr(
7317                                 p,
7318                                 flag | EXP_TILDE | EXP_WORD
7319                         );
7320                         goto end;
7321                 }
7322                 goto record;
7323         }
7324
7325         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7326                 if (varlen >= 0)
7327                         goto record;
7328
7329                 subevalvar(p, var, 0, subtype, startloc, varflags,
7330                            flag & ~QUOTES_ESC);
7331                 varflags &= ~VSNUL;
7332                 /*
7333                  * Remove any recorded regions beyond
7334                  * start of variable
7335                  */
7336                 removerecordregions(startloc);
7337                 goto again;
7338         }
7339
7340         if (varlen < 0 && uflag)
7341                 varunset(p, var, 0, 0);
7342
7343         if (subtype == VSLENGTH) {
7344                 cvtnum(varlen > 0 ? varlen : 0);
7345                 goto record;
7346         }
7347
7348         if (subtype == VSNORMAL) {
7349  record:
7350                 if (!easy)
7351                         goto end;
7352                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7353                 goto end;
7354         }
7355
7356 #if DEBUG
7357         switch (subtype) {
7358         case VSTRIMLEFT:
7359         case VSTRIMLEFTMAX:
7360         case VSTRIMRIGHT:
7361         case VSTRIMRIGHTMAX:
7362 #if BASH_SUBSTR
7363         case VSSUBSTR:
7364 #endif
7365 #if BASH_PATTERN_SUBST
7366         case VSREPLACE:
7367         case VSREPLACEALL:
7368 #endif
7369                 break;
7370         default:
7371                 abort();
7372         }
7373 #endif
7374
7375         if (varlen >= 0) {
7376                 /*
7377                  * Terminate the string and start recording the pattern
7378                  * right after it
7379                  */
7380                 STPUTC('\0', expdest);
7381                 patloc = expdest - (char *)stackblock();
7382                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7383                                 startloc, varflags, flag)) {
7384                         int amount = expdest - (
7385                                 (char *)stackblock() + patloc - 1
7386                         );
7387                         STADJUST(-amount, expdest);
7388                 }
7389                 /* Remove any recorded regions beyond start of variable */
7390                 removerecordregions(startloc);
7391                 goto record;
7392         }
7393
7394  end:
7395         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7396                 int nesting = 1;
7397                 for (;;) {
7398                         unsigned char c = *p++;
7399                         if (c == CTLESC)
7400                                 p++;
7401                         else if (c == CTLBACKQ) {
7402                                 if (varlen >= 0)
7403                                         argbackq = argbackq->next;
7404                         } else if (c == CTLVAR) {
7405                                 if ((*p++ & VSTYPE) != VSNORMAL)
7406                                         nesting++;
7407                         } else if (c == CTLENDVAR) {
7408                                 if (--nesting == 0)
7409                                         break;
7410                         }
7411                 }
7412         }
7413         return p;
7414 }
7415
7416 /*
7417  * Add a file name to the list.
7418  */
7419 static void
7420 addfname(const char *name)
7421 {
7422         struct strlist *sp;
7423
7424         sp = stzalloc(sizeof(*sp));
7425         sp->text = sstrdup(name);
7426         *exparg.lastp = sp;
7427         exparg.lastp = &sp->next;
7428 }
7429
7430 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7431 static int
7432 hasmeta(const char *p)
7433 {
7434         static const char chars[] ALIGN1 = {
7435                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7436         };
7437
7438         for (;;) {
7439                 p = strpbrk(p, chars);
7440                 if (!p)
7441                         break;
7442                 switch ((unsigned char)*p) {
7443                 case CTLQUOTEMARK:
7444                         for (;;) {
7445                                 p++;
7446                                 if ((unsigned char)*p == CTLQUOTEMARK)
7447                                         break;
7448                                 if ((unsigned char)*p == CTLESC)
7449                                         p++;
7450                                 if (*p == '\0') /* huh? */
7451                                         return 0;
7452                         }
7453                         break;
7454                 case '\\':
7455                 case CTLESC:
7456                         p++;
7457                         if (*p == '\0')
7458                                 return 0;
7459                         break;
7460                 case '[':
7461                         if (!strchr(p + 1, ']')) {
7462                                 /* It's not a properly closed [] pattern,
7463                                  * but other metas may follow. Continue checking.
7464                                  * my[file* _is_ globbed by bash
7465                                  * and matches filenames like "my[file1".
7466                                  */
7467                                 break;
7468                         }
7469                         /* fallthrough */
7470                 default:
7471                 /* case '*': */
7472                 /* case '?': */
7473                         return 1;
7474                 }
7475                 p++;
7476         }
7477
7478         return 0;
7479 }
7480
7481 /* If we want to use glob() from libc... */
7482 #if !ENABLE_ASH_INTERNAL_GLOB
7483
7484 /* Add the result of glob() to the list */
7485 static void
7486 addglob(const glob_t *pglob)
7487 {
7488         char **p = pglob->gl_pathv;
7489
7490         do {
7491                 addfname(*p);
7492         } while (*++p);
7493 }
7494 static void
7495 expandmeta(struct strlist *str /*, int flag*/)
7496 {
7497         /* TODO - EXP_REDIR */
7498
7499         while (str) {
7500                 char *p;
7501                 glob_t pglob;
7502                 int i;
7503
7504                 if (fflag)
7505                         goto nometa;
7506
7507                 if (!hasmeta(str->text))
7508                         goto nometa;
7509
7510                 INT_OFF;
7511                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7512 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7513 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7514 //
7515 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7516 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7517 // Which means you need to unescape the string, right? Not so fast:
7518 // if there _is_ a file named "file\?" (with backslash), it is returned
7519 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7520 // You DON'T KNOW by looking at the result whether you need to unescape it.
7521 //
7522 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7523 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7524 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7525 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7526 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7527 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7528                 i = glob(p, 0, NULL, &pglob);
7529                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7530                 if (p != str->text)
7531                         free(p);
7532                 switch (i) {
7533                 case 0:
7534 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7535                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7536                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7537                                 goto nometa2;
7538 #endif
7539                         addglob(&pglob);
7540                         globfree(&pglob);
7541                         INT_ON;
7542                         break;
7543                 case GLOB_NOMATCH:
7544  //nometa2:
7545                         globfree(&pglob);
7546                         INT_ON;
7547  nometa:
7548                         *exparg.lastp = str;
7549                         rmescapes(str->text, 0, NULL);
7550                         exparg.lastp = &str->next;
7551                         break;
7552                 default:        /* GLOB_NOSPACE */
7553                         globfree(&pglob);
7554                         INT_ON;
7555                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7556                 }
7557                 str = str->next;
7558         }
7559 }
7560
7561 #else
7562 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7563
7564 /*
7565  * Do metacharacter (i.e. *, ?, [...]) expansion.
7566  */
7567 static void
7568 expmeta(char *expdir, char *enddir, char *name)
7569 {
7570         char *p;
7571         const char *cp;
7572         char *start;
7573         char *endname;
7574         int metaflag;
7575         struct stat statb;
7576         DIR *dirp;
7577         struct dirent *dp;
7578         int atend;
7579         int matchdot;
7580         int esc;
7581
7582         metaflag = 0;
7583         start = name;
7584         for (p = name; esc = 0, *p; p += esc + 1) {
7585                 if (*p == '*' || *p == '?')
7586                         metaflag = 1;
7587                 else if (*p == '[') {
7588                         char *q = p + 1;
7589                         if (*q == '!')
7590                                 q++;
7591                         for (;;) {
7592                                 if (*q == '\\')
7593                                         q++;
7594                                 if (*q == '/' || *q == '\0')
7595                                         break;
7596                                 if (*++q == ']') {
7597                                         metaflag = 1;
7598                                         break;
7599                                 }
7600                         }
7601                 } else {
7602                         if (*p == '\\')
7603                                 esc++;
7604                         if (p[esc] == '/') {
7605                                 if (metaflag)
7606                                         break;
7607                                 start = p + esc + 1;
7608                         }
7609                 }
7610         }
7611         if (metaflag == 0) {    /* we've reached the end of the file name */
7612                 if (enddir != expdir)
7613                         metaflag++;
7614                 p = name;
7615                 do {
7616                         if (*p == '\\')
7617                                 p++;
7618                         *enddir++ = *p;
7619                 } while (*p++);
7620                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7621                         addfname(expdir);
7622                 return;
7623         }
7624         endname = p;
7625         if (name < start) {
7626                 p = name;
7627                 do {
7628                         if (*p == '\\')
7629                                 p++;
7630                         *enddir++ = *p++;
7631                 } while (p < start);
7632         }
7633         if (enddir == expdir) {
7634                 cp = ".";
7635         } else if (enddir == expdir + 1 && *expdir == '/') {
7636                 cp = "/";
7637         } else {
7638                 cp = expdir;
7639                 enddir[-1] = '\0';
7640         }
7641         dirp = opendir(cp);
7642         if (dirp == NULL)
7643                 return;
7644         if (enddir != expdir)
7645                 enddir[-1] = '/';
7646         if (*endname == 0) {
7647                 atend = 1;
7648         } else {
7649                 atend = 0;
7650                 *endname = '\0';
7651                 endname += esc + 1;
7652         }
7653         matchdot = 0;
7654         p = start;
7655         if (*p == '\\')
7656                 p++;
7657         if (*p == '.')
7658                 matchdot++;
7659         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7660                 if (dp->d_name[0] == '.' && !matchdot)
7661                         continue;
7662                 if (pmatch(start, dp->d_name)) {
7663                         if (atend) {
7664                                 strcpy(enddir, dp->d_name);
7665                                 addfname(expdir);
7666                         } else {
7667                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7668                                         continue;
7669                                 p[-1] = '/';
7670                                 expmeta(expdir, p, endname);
7671                         }
7672                 }
7673         }
7674         closedir(dirp);
7675         if (!atend)
7676                 endname[-esc - 1] = esc ? '\\' : '/';
7677 }
7678
7679 static struct strlist *
7680 msort(struct strlist *list, int len)
7681 {
7682         struct strlist *p, *q = NULL;
7683         struct strlist **lpp;
7684         int half;
7685         int n;
7686
7687         if (len <= 1)
7688                 return list;
7689         half = len >> 1;
7690         p = list;
7691         for (n = half; --n >= 0;) {
7692                 q = p;
7693                 p = p->next;
7694         }
7695         q->next = NULL;                 /* terminate first half of list */
7696         q = msort(list, half);          /* sort first half of list */
7697         p = msort(p, len - half);               /* sort second half */
7698         lpp = &list;
7699         for (;;) {
7700 #if ENABLE_LOCALE_SUPPORT
7701                 if (strcoll(p->text, q->text) < 0)
7702 #else
7703                 if (strcmp(p->text, q->text) < 0)
7704 #endif
7705                                                 {
7706                         *lpp = p;
7707                         lpp = &p->next;
7708                         p = *lpp;
7709                         if (p == NULL) {
7710                                 *lpp = q;
7711                                 break;
7712                         }
7713                 } else {
7714                         *lpp = q;
7715                         lpp = &q->next;
7716                         q = *lpp;
7717                         if (q == NULL) {
7718                                 *lpp = p;
7719                                 break;
7720                         }
7721                 }
7722         }
7723         return list;
7724 }
7725
7726 /*
7727  * Sort the results of file name expansion.  It calculates the number of
7728  * strings to sort and then calls msort (short for merge sort) to do the
7729  * work.
7730  */
7731 static struct strlist *
7732 expsort(struct strlist *str)
7733 {
7734         int len;
7735         struct strlist *sp;
7736
7737         len = 0;
7738         for (sp = str; sp; sp = sp->next)
7739                 len++;
7740         return msort(str, len);
7741 }
7742
7743 static void
7744 expandmeta(struct strlist *str /*, int flag*/)
7745 {
7746         /* TODO - EXP_REDIR */
7747
7748         while (str) {
7749                 char *expdir;
7750                 struct strlist **savelastp;
7751                 struct strlist *sp;
7752                 char *p;
7753
7754                 if (fflag)
7755                         goto nometa;
7756                 if (!hasmeta(str->text))
7757                         goto nometa;
7758                 savelastp = exparg.lastp;
7759
7760                 INT_OFF;
7761                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7762                 {
7763                         int i = strlen(str->text);
7764 //BUGGY estimation of how long expanded name can be
7765                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7766                 }
7767                 expmeta(expdir, expdir, p);
7768                 free(expdir);
7769                 if (p != str->text)
7770                         free(p);
7771                 INT_ON;
7772                 if (exparg.lastp == savelastp) {
7773                         /*
7774                          * no matches
7775                          */
7776  nometa:
7777                         *exparg.lastp = str;
7778                         rmescapes(str->text, 0, NULL);
7779                         exparg.lastp = &str->next;
7780                 } else {
7781                         *exparg.lastp = NULL;
7782                         *savelastp = sp = expsort(*savelastp);
7783                         while (sp->next != NULL)
7784                                 sp = sp->next;
7785                         exparg.lastp = &sp->next;
7786                 }
7787                 str = str->next;
7788         }
7789 }
7790 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7791
7792 /*
7793  * Perform variable substitution and command substitution on an argument,
7794  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7795  * perform splitting and file name expansion.  When arglist is NULL, perform
7796  * here document expansion.
7797  */
7798 static void
7799 expandarg(union node *arg, struct arglist *arglist, int flag)
7800 {
7801         struct strlist *sp;
7802         char *p;
7803
7804         argbackq = arg->narg.backquote;
7805         STARTSTACKSTR(expdest);
7806         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7807         argstr(arg->narg.text, flag);
7808         p = _STPUTC('\0', expdest);
7809         expdest = p - 1;
7810         if (arglist == NULL) {
7811                 /* here document expanded */
7812                 goto out;
7813         }
7814         p = grabstackstr(p);
7815         TRACE(("expandarg: p:'%s'\n", p));
7816         exparg.lastp = &exparg.list;
7817         /*
7818          * TODO - EXP_REDIR
7819          */
7820         if (flag & EXP_FULL) {
7821                 ifsbreakup(p, &exparg);
7822                 *exparg.lastp = NULL;
7823                 exparg.lastp = &exparg.list;
7824                 expandmeta(exparg.list /*, flag*/);
7825         } else {
7826                 sp = stzalloc(sizeof(*sp));
7827                 sp->text = p;
7828                 *exparg.lastp = sp;
7829                 exparg.lastp = &sp->next;
7830         }
7831         *exparg.lastp = NULL;
7832         if (exparg.list) {
7833                 *arglist->lastp = exparg.list;
7834                 arglist->lastp = exparg.lastp;
7835         }
7836
7837  out:
7838         ifsfree();
7839 }
7840
7841 /*
7842  * Expand shell variables and backquotes inside a here document.
7843  */
7844 static void
7845 expandhere(union node *arg, int fd)
7846 {
7847         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7848         full_write(fd, stackblock(), expdest - (char *)stackblock());
7849 }
7850
7851 /*
7852  * Returns true if the pattern matches the string.
7853  */
7854 static int
7855 patmatch(char *pattern, const char *string)
7856 {
7857         char *p = preglob(pattern, 0);
7858         int r = pmatch(p, string);
7859         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7860         return r;
7861 }
7862
7863 /*
7864  * See if a pattern matches in a case statement.
7865  */
7866 static int
7867 casematch(union node *pattern, char *val)
7868 {
7869         struct stackmark smark;
7870         int result;
7871
7872         setstackmark(&smark);
7873         argbackq = pattern->narg.backquote;
7874         STARTSTACKSTR(expdest);
7875         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7876         STACKSTRNUL(expdest);
7877         ifsfree();
7878         result = patmatch(stackblock(), val);
7879         popstackmark(&smark);
7880         return result;
7881 }
7882
7883
7884 /* ============ find_command */
7885
7886 struct builtincmd {
7887         const char *name;
7888         int (*builtin)(int, char **) FAST_FUNC;
7889         /* unsigned flags; */
7890 };
7891 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7892 /* "regular" builtins always take precedence over commands,
7893  * regardless of PATH=....%builtin... position */
7894 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7895 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7896
7897 struct cmdentry {
7898         smallint cmdtype;       /* CMDxxx */
7899         union param {
7900                 int index;
7901                 /* index >= 0 for commands without path (slashes) */
7902                 /* (TODO: what exactly does the value mean? PATH position?) */
7903                 /* index == -1 for commands with slashes */
7904                 /* index == (-2 - applet_no) for NOFORK applets */
7905                 const struct builtincmd *cmd;
7906                 struct funcnode *func;
7907         } u;
7908 };
7909 /* values of cmdtype */
7910 #define CMDUNKNOWN      -1      /* no entry in table for command */
7911 #define CMDNORMAL       0       /* command is an executable program */
7912 #define CMDFUNCTION     1       /* command is a shell function */
7913 #define CMDBUILTIN      2       /* command is a shell builtin */
7914
7915 /* action to find_command() */
7916 #define DO_ERR          0x01    /* prints errors */
7917 #define DO_ABS          0x02    /* checks absolute paths */
7918 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7919 #define DO_ALTPATH      0x08    /* using alternate path */
7920 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7921
7922 static void find_command(char *, struct cmdentry *, int, const char *);
7923
7924
7925 /* ============ Hashing commands */
7926
7927 /*
7928  * When commands are first encountered, they are entered in a hash table.
7929  * This ensures that a full path search will not have to be done for them
7930  * on each invocation.
7931  *
7932  * We should investigate converting to a linear search, even though that
7933  * would make the command name "hash" a misnomer.
7934  */
7935
7936 struct tblentry {
7937         struct tblentry *next;  /* next entry in hash chain */
7938         union param param;      /* definition of builtin function */
7939         smallint cmdtype;       /* CMDxxx */
7940         char rehash;            /* if set, cd done since entry created */
7941         char cmdname[1];        /* name of command */
7942 };
7943
7944 static struct tblentry **cmdtable;
7945 #define INIT_G_cmdtable() do { \
7946         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7947 } while (0)
7948
7949 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7950
7951
7952 static void
7953 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7954 {
7955 #if ENABLE_FEATURE_SH_STANDALONE
7956         if (applet_no >= 0) {
7957                 if (APPLET_IS_NOEXEC(applet_no)) {
7958                         clearenv();
7959                         while (*envp)
7960                                 putenv(*envp++);
7961                         popredir(/*drop:*/ 1);
7962                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7963                 }
7964                 /* re-exec ourselves with the new arguments */
7965                 execve(bb_busybox_exec_path, argv, envp);
7966                 /* If they called chroot or otherwise made the binary no longer
7967                  * executable, fall through */
7968         }
7969 #endif
7970
7971  repeat:
7972 #ifdef SYSV
7973         do {
7974                 execve(cmd, argv, envp);
7975         } while (errno == EINTR);
7976 #else
7977         execve(cmd, argv, envp);
7978 #endif
7979         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7980                 /* Run "cmd" as a shell script:
7981                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7982                  * "If the execve() function fails with ENOEXEC, the shell
7983                  * shall execute a command equivalent to having a shell invoked
7984                  * with the command name as its first operand,
7985                  * with any remaining arguments passed to the new shell"
7986                  *
7987                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7988                  * just call ourselves.
7989                  *
7990                  * Note that bash reads ~80 chars of the file, and if it sees
7991                  * a zero byte before it sees newline, it doesn't try to
7992                  * interpret it, but fails with "cannot execute binary file"
7993                  * message and exit code 126. For one, this prevents attempts
7994                  * to interpret foreign ELF binaries as shell scripts.
7995                  */
7996                 argv[0] = (char*) cmd;
7997                 cmd = bb_busybox_exec_path;
7998                 /* NB: this is only possible because all callers of shellexec()
7999                  * ensure that the argv[-1] slot exists!
8000                  */
8001                 argv--;
8002                 argv[0] = (char*) "ash";
8003                 goto repeat;
8004         }
8005 }
8006
8007 /*
8008  * Exec a program.  Never returns.  If you change this routine, you may
8009  * have to change the find_command routine as well.
8010  * argv[-1] must exist and be writable! See tryexec() for why.
8011  */
8012 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8013 static void shellexec(char *prog, char **argv, const char *path, int idx)
8014 {
8015         char *cmdname;
8016         int e;
8017         char **envp;
8018         int exerrno;
8019         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8020
8021         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8022         if (strchr(prog, '/') != NULL
8023 #if ENABLE_FEATURE_SH_STANDALONE
8024          || (applet_no = find_applet_by_name(prog)) >= 0
8025 #endif
8026         ) {
8027                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8028                 if (applet_no >= 0) {
8029                         /* We tried execing ourself, but it didn't work.
8030                          * Maybe /proc/self/exe doesn't exist?
8031                          * Try $PATH search.
8032                          */
8033                         goto try_PATH;
8034                 }
8035                 e = errno;
8036         } else {
8037  try_PATH:
8038                 e = ENOENT;
8039                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8040                         if (--idx < 0 && pathopt == NULL) {
8041                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8042                                 if (errno != ENOENT && errno != ENOTDIR)
8043                                         e = errno;
8044                         }
8045                         stunalloc(cmdname);
8046                 }
8047         }
8048
8049         /* Map to POSIX errors */
8050         switch (e) {
8051         case EACCES:
8052                 exerrno = 126;
8053                 break;
8054         case ENOENT:
8055                 exerrno = 127;
8056                 break;
8057         default:
8058                 exerrno = 2;
8059                 break;
8060         }
8061         exitstatus = exerrno;
8062         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8063                 prog, e, suppress_int));
8064         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8065         /* NOTREACHED */
8066 }
8067
8068 static void
8069 printentry(struct tblentry *cmdp)
8070 {
8071         int idx;
8072         const char *path;
8073         char *name;
8074
8075         idx = cmdp->param.index;
8076         path = pathval();
8077         do {
8078                 name = path_advance(&path, cmdp->cmdname);
8079                 stunalloc(name);
8080         } while (--idx >= 0);
8081         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8082 }
8083
8084 /*
8085  * Clear out command entries.  The argument specifies the first entry in
8086  * PATH which has changed.
8087  */
8088 static void
8089 clearcmdentry(int firstchange)
8090 {
8091         struct tblentry **tblp;
8092         struct tblentry **pp;
8093         struct tblentry *cmdp;
8094
8095         INT_OFF;
8096         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8097                 pp = tblp;
8098                 while ((cmdp = *pp) != NULL) {
8099                         if ((cmdp->cmdtype == CMDNORMAL &&
8100                              cmdp->param.index >= firstchange)
8101                          || (cmdp->cmdtype == CMDBUILTIN &&
8102                              builtinloc >= firstchange)
8103                         ) {
8104                                 *pp = cmdp->next;
8105                                 free(cmdp);
8106                         } else {
8107                                 pp = &cmdp->next;
8108                         }
8109                 }
8110         }
8111         INT_ON;
8112 }
8113
8114 /*
8115  * Locate a command in the command hash table.  If "add" is nonzero,
8116  * add the command to the table if it is not already present.  The
8117  * variable "lastcmdentry" is set to point to the address of the link
8118  * pointing to the entry, so that delete_cmd_entry can delete the
8119  * entry.
8120  *
8121  * Interrupts must be off if called with add != 0.
8122  */
8123 static struct tblentry **lastcmdentry;
8124
8125 static struct tblentry *
8126 cmdlookup(const char *name, int add)
8127 {
8128         unsigned int hashval;
8129         const char *p;
8130         struct tblentry *cmdp;
8131         struct tblentry **pp;
8132
8133         p = name;
8134         hashval = (unsigned char)*p << 4;
8135         while (*p)
8136                 hashval += (unsigned char)*p++;
8137         hashval &= 0x7FFF;
8138         pp = &cmdtable[hashval % CMDTABLESIZE];
8139         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8140                 if (strcmp(cmdp->cmdname, name) == 0)
8141                         break;
8142                 pp = &cmdp->next;
8143         }
8144         if (add && cmdp == NULL) {
8145                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8146                                 + strlen(name)
8147                                 /* + 1 - already done because
8148                                  * tblentry::cmdname is char[1] */);
8149                 /*cmdp->next = NULL; - ckzalloc did it */
8150                 cmdp->cmdtype = CMDUNKNOWN;
8151                 strcpy(cmdp->cmdname, name);
8152         }
8153         lastcmdentry = pp;
8154         return cmdp;
8155 }
8156
8157 /*
8158  * Delete the command entry returned on the last lookup.
8159  */
8160 static void
8161 delete_cmd_entry(void)
8162 {
8163         struct tblentry *cmdp;
8164
8165         INT_OFF;
8166         cmdp = *lastcmdentry;
8167         *lastcmdentry = cmdp->next;
8168         if (cmdp->cmdtype == CMDFUNCTION)
8169                 freefunc(cmdp->param.func);
8170         free(cmdp);
8171         INT_ON;
8172 }
8173
8174 /*
8175  * Add a new command entry, replacing any existing command entry for
8176  * the same name - except special builtins.
8177  */
8178 static void
8179 addcmdentry(char *name, struct cmdentry *entry)
8180 {
8181         struct tblentry *cmdp;
8182
8183         cmdp = cmdlookup(name, 1);
8184         if (cmdp->cmdtype == CMDFUNCTION) {
8185                 freefunc(cmdp->param.func);
8186         }
8187         cmdp->cmdtype = entry->cmdtype;
8188         cmdp->param = entry->u;
8189         cmdp->rehash = 0;
8190 }
8191
8192 static int FAST_FUNC
8193 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8194 {
8195         struct tblentry **pp;
8196         struct tblentry *cmdp;
8197         int c;
8198         struct cmdentry entry;
8199         char *name;
8200
8201         if (nextopt("r") != '\0') {
8202                 clearcmdentry(0);
8203                 return 0;
8204         }
8205
8206         if (*argptr == NULL) {
8207                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8208                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8209                                 if (cmdp->cmdtype == CMDNORMAL)
8210                                         printentry(cmdp);
8211                         }
8212                 }
8213                 return 0;
8214         }
8215
8216         c = 0;
8217         while ((name = *argptr) != NULL) {
8218                 cmdp = cmdlookup(name, 0);
8219                 if (cmdp != NULL
8220                  && (cmdp->cmdtype == CMDNORMAL
8221                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8222                 ) {
8223                         delete_cmd_entry();
8224                 }
8225                 find_command(name, &entry, DO_ERR, pathval());
8226                 if (entry.cmdtype == CMDUNKNOWN)
8227                         c = 1;
8228                 argptr++;
8229         }
8230         return c;
8231 }
8232
8233 /*
8234  * Called when a cd is done.  Marks all commands so the next time they
8235  * are executed they will be rehashed.
8236  */
8237 static void
8238 hashcd(void)
8239 {
8240         struct tblentry **pp;
8241         struct tblentry *cmdp;
8242
8243         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8244                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8245                         if (cmdp->cmdtype == CMDNORMAL
8246                          || (cmdp->cmdtype == CMDBUILTIN
8247                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8248                              && builtinloc > 0)
8249                         ) {
8250                                 cmdp->rehash = 1;
8251                         }
8252                 }
8253         }
8254 }
8255
8256 /*
8257  * Fix command hash table when PATH changed.
8258  * Called before PATH is changed.  The argument is the new value of PATH;
8259  * pathval() still returns the old value at this point.
8260  * Called with interrupts off.
8261  */
8262 static void FAST_FUNC
8263 changepath(const char *new)
8264 {
8265         const char *old;
8266         int firstchange;
8267         int idx;
8268         int idx_bltin;
8269
8270         old = pathval();
8271         firstchange = 9999;     /* assume no change */
8272         idx = 0;
8273         idx_bltin = -1;
8274         for (;;) {
8275                 if (*old != *new) {
8276                         firstchange = idx;
8277                         if ((*old == '\0' && *new == ':')
8278                          || (*old == ':' && *new == '\0')
8279                         ) {
8280                                 firstchange++;
8281                         }
8282                         old = new;      /* ignore subsequent differences */
8283                 }
8284                 if (*new == '\0')
8285                         break;
8286                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8287                         idx_bltin = idx;
8288                 if (*new == ':')
8289                         idx++;
8290                 new++;
8291                 old++;
8292         }
8293         if (builtinloc < 0 && idx_bltin >= 0)
8294                 builtinloc = idx_bltin;             /* zap builtins */
8295         if (builtinloc >= 0 && idx_bltin < 0)
8296                 firstchange = 0;
8297         clearcmdentry(firstchange);
8298         builtinloc = idx_bltin;
8299 }
8300 enum {
8301         TEOF,
8302         TNL,
8303         TREDIR,
8304         TWORD,
8305         TSEMI,
8306         TBACKGND,
8307         TAND,
8308         TOR,
8309         TPIPE,
8310         TLP,
8311         TRP,
8312         TENDCASE,
8313         TENDBQUOTE,
8314         TNOT,
8315         TCASE,
8316         TDO,
8317         TDONE,
8318         TELIF,
8319         TELSE,
8320         TESAC,
8321         TFI,
8322         TFOR,
8323 #if BASH_FUNCTION
8324         TFUNCTION,
8325 #endif
8326         TIF,
8327         TIN,
8328         TTHEN,
8329         TUNTIL,
8330         TWHILE,
8331         TBEGIN,
8332         TEND
8333 };
8334 typedef smallint token_id_t;
8335
8336 /* Nth bit indicates if token marks the end of a list */
8337 enum {
8338         tokendlist = 0
8339         /*  0 */ | (1u << TEOF)
8340         /*  1 */ | (0u << TNL)
8341         /*  2 */ | (0u << TREDIR)
8342         /*  3 */ | (0u << TWORD)
8343         /*  4 */ | (0u << TSEMI)
8344         /*  5 */ | (0u << TBACKGND)
8345         /*  6 */ | (0u << TAND)
8346         /*  7 */ | (0u << TOR)
8347         /*  8 */ | (0u << TPIPE)
8348         /*  9 */ | (0u << TLP)
8349         /* 10 */ | (1u << TRP)
8350         /* 11 */ | (1u << TENDCASE)
8351         /* 12 */ | (1u << TENDBQUOTE)
8352         /* 13 */ | (0u << TNOT)
8353         /* 14 */ | (0u << TCASE)
8354         /* 15 */ | (1u << TDO)
8355         /* 16 */ | (1u << TDONE)
8356         /* 17 */ | (1u << TELIF)
8357         /* 18 */ | (1u << TELSE)
8358         /* 19 */ | (1u << TESAC)
8359         /* 20 */ | (1u << TFI)
8360         /* 21 */ | (0u << TFOR)
8361 #if BASH_FUNCTION
8362         /* 22 */ | (0u << TFUNCTION)
8363 #endif
8364         /* 23 */ | (0u << TIF)
8365         /* 24 */ | (0u << TIN)
8366         /* 25 */ | (1u << TTHEN)
8367         /* 26 */ | (0u << TUNTIL)
8368         /* 27 */ | (0u << TWHILE)
8369         /* 28 */ | (0u << TBEGIN)
8370         /* 29 */ | (1u << TEND)
8371         , /* thus far 29 bits used */
8372 };
8373
8374 static const char *const tokname_array[] = {
8375         "end of file",
8376         "newline",
8377         "redirection",
8378         "word",
8379         ";",
8380         "&",
8381         "&&",
8382         "||",
8383         "|",
8384         "(",
8385         ")",
8386         ";;",
8387         "`",
8388 #define KWDOFFSET 13
8389         /* the following are keywords */
8390         "!",
8391         "case",
8392         "do",
8393         "done",
8394         "elif",
8395         "else",
8396         "esac",
8397         "fi",
8398         "for",
8399 #if BASH_FUNCTION
8400         "function",
8401 #endif
8402         "if",
8403         "in",
8404         "then",
8405         "until",
8406         "while",
8407         "{",
8408         "}",
8409 };
8410
8411 /* Wrapper around strcmp for qsort/bsearch/... */
8412 static int
8413 pstrcmp(const void *a, const void *b)
8414 {
8415         return strcmp((char*)a, *(char**)b);
8416 }
8417
8418 static const char *const *
8419 findkwd(const char *s)
8420 {
8421         return bsearch(s, tokname_array + KWDOFFSET,
8422                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8423                         sizeof(tokname_array[0]), pstrcmp);
8424 }
8425
8426 /*
8427  * Locate and print what a word is...
8428  */
8429 static int
8430 describe_command(char *command, const char *path, int describe_command_verbose)
8431 {
8432         struct cmdentry entry;
8433 #if ENABLE_ASH_ALIAS
8434         const struct alias *ap;
8435 #endif
8436
8437         path = path ? path : pathval();
8438
8439         if (describe_command_verbose) {
8440                 out1str(command);
8441         }
8442
8443         /* First look at the keywords */
8444         if (findkwd(command)) {
8445                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8446                 goto out;
8447         }
8448
8449 #if ENABLE_ASH_ALIAS
8450         /* Then look at the aliases */
8451         ap = lookupalias(command, 0);
8452         if (ap != NULL) {
8453                 if (!describe_command_verbose) {
8454                         out1str("alias ");
8455                         printalias(ap);
8456                         return 0;
8457                 }
8458                 out1fmt(" is an alias for %s", ap->val);
8459                 goto out;
8460         }
8461 #endif
8462         /* Brute force */
8463         find_command(command, &entry, DO_ABS, path);
8464
8465         switch (entry.cmdtype) {
8466         case CMDNORMAL: {
8467                 int j = entry.u.index;
8468                 char *p;
8469                 if (j < 0) {
8470                         p = command;
8471                 } else {
8472                         do {
8473                                 p = path_advance(&path, command);
8474                                 stunalloc(p);
8475                         } while (--j >= 0);
8476                 }
8477                 if (describe_command_verbose) {
8478                         out1fmt(" is %s", p);
8479                 } else {
8480                         out1str(p);
8481                 }
8482                 break;
8483         }
8484
8485         case CMDFUNCTION:
8486                 if (describe_command_verbose) {
8487                         out1str(" is a shell function");
8488                 } else {
8489                         out1str(command);
8490                 }
8491                 break;
8492
8493         case CMDBUILTIN:
8494                 if (describe_command_verbose) {
8495                         out1fmt(" is a %sshell builtin",
8496                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8497                                         "special " : nullstr
8498                         );
8499                 } else {
8500                         out1str(command);
8501                 }
8502                 break;
8503
8504         default:
8505                 if (describe_command_verbose) {
8506                         out1str(": not found\n");
8507                 }
8508                 return 127;
8509         }
8510  out:
8511         out1str("\n");
8512         return 0;
8513 }
8514
8515 static int FAST_FUNC
8516 typecmd(int argc UNUSED_PARAM, char **argv)
8517 {
8518         int i = 1;
8519         int err = 0;
8520         int verbose = 1;
8521
8522         /* type -p ... ? (we don't bother checking for 'p') */
8523         if (argv[1] && argv[1][0] == '-') {
8524                 i++;
8525                 verbose = 0;
8526         }
8527         while (argv[i]) {
8528                 err |= describe_command(argv[i++], NULL, verbose);
8529         }
8530         return err;
8531 }
8532
8533 #if ENABLE_ASH_CMDCMD
8534 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8535 static char **
8536 parse_command_args(char **argv, const char **path)
8537 {
8538         char *cp, c;
8539
8540         for (;;) {
8541                 cp = *++argv;
8542                 if (!cp)
8543                         return NULL;
8544                 if (*cp++ != '-')
8545                         break;
8546                 c = *cp++;
8547                 if (!c)
8548                         break;
8549                 if (c == '-' && !*cp) {
8550                         if (!*++argv)
8551                                 return NULL;
8552                         break;
8553                 }
8554                 do {
8555                         switch (c) {
8556                         case 'p':
8557                                 *path = bb_default_path;
8558                                 break;
8559                         default:
8560                                 /* run 'typecmd' for other options */
8561                                 return NULL;
8562                         }
8563                         c = *cp++;
8564                 } while (c);
8565         }
8566         return argv;
8567 }
8568
8569 static int FAST_FUNC
8570 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8571 {
8572         char *cmd;
8573         int c;
8574         enum {
8575                 VERIFY_BRIEF = 1,
8576                 VERIFY_VERBOSE = 2,
8577         } verify = 0;
8578         const char *path = NULL;
8579
8580         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8581          * never reaches this function.
8582          */
8583
8584         while ((c = nextopt("pvV")) != '\0')
8585                 if (c == 'V')
8586                         verify |= VERIFY_VERBOSE;
8587                 else if (c == 'v')
8588                         /*verify |= VERIFY_BRIEF*/;
8589 #if DEBUG
8590                 else if (c != 'p')
8591                         abort();
8592 #endif
8593                 else
8594                         path = bb_default_path;
8595
8596         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8597         cmd = *argptr;
8598         if (/*verify && */ cmd)
8599                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8600
8601         return 0;
8602 }
8603 #endif
8604
8605
8606 /*static int funcblocksize;     // size of structures in function */
8607 /*static int funcstringsize;    // size of strings in node */
8608 static void *funcblock;         /* block to allocate function from */
8609 static char *funcstring_end;    /* end of block to allocate strings from */
8610
8611 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8612         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8613         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8614         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8615         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8616         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8617         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8618         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8619         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8620         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8621         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8622         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8623         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8624         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8625         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8626         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8627         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8628         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8629 #if BASH_REDIR_OUTPUT
8630         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8631 #endif
8632         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8633         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8634         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8635         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8636         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8637         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8638         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8639         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8640         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8641 };
8642
8643 static int calcsize(int funcblocksize, union node *n);
8644
8645 static int
8646 sizenodelist(int funcblocksize, struct nodelist *lp)
8647 {
8648         while (lp) {
8649                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8650                 funcblocksize = calcsize(funcblocksize, lp->n);
8651                 lp = lp->next;
8652         }
8653         return funcblocksize;
8654 }
8655
8656 static int
8657 calcsize(int funcblocksize, union node *n)
8658 {
8659         if (n == NULL)
8660                 return funcblocksize;
8661         funcblocksize += nodesize[n->type];
8662         switch (n->type) {
8663         case NCMD:
8664                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8665                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8666                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8667                 break;
8668         case NPIPE:
8669                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8670                 break;
8671         case NREDIR:
8672         case NBACKGND:
8673         case NSUBSHELL:
8674                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8675                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8676                 break;
8677         case NAND:
8678         case NOR:
8679         case NSEMI:
8680         case NWHILE:
8681         case NUNTIL:
8682                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8683                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8684                 break;
8685         case NIF:
8686                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8687                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8688                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8689                 break;
8690         case NFOR:
8691                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8692                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8693                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8694                 break;
8695         case NCASE:
8696                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8697                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8698                 break;
8699         case NCLIST:
8700                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8701                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8702                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8703                 break;
8704         case NDEFUN:
8705                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8706                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8707                 break;
8708         case NARG:
8709                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8710                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8711                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8712                 break;
8713         case NTO:
8714 #if BASH_REDIR_OUTPUT
8715         case NTO2:
8716 #endif
8717         case NCLOBBER:
8718         case NFROM:
8719         case NFROMTO:
8720         case NAPPEND:
8721                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8722                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8723                 break;
8724         case NTOFD:
8725         case NFROMFD:
8726                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8727                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8728         break;
8729         case NHERE:
8730         case NXHERE:
8731                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8732                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8733                 break;
8734         case NNOT:
8735                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8736                 break;
8737         };
8738         return funcblocksize;
8739 }
8740
8741 static char *
8742 nodeckstrdup(char *s)
8743 {
8744         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8745         return strcpy(funcstring_end, s);
8746 }
8747
8748 static union node *copynode(union node *);
8749
8750 static struct nodelist *
8751 copynodelist(struct nodelist *lp)
8752 {
8753         struct nodelist *start;
8754         struct nodelist **lpp;
8755
8756         lpp = &start;
8757         while (lp) {
8758                 *lpp = funcblock;
8759                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8760                 (*lpp)->n = copynode(lp->n);
8761                 lp = lp->next;
8762                 lpp = &(*lpp)->next;
8763         }
8764         *lpp = NULL;
8765         return start;
8766 }
8767
8768 static union node *
8769 copynode(union node *n)
8770 {
8771         union node *new;
8772
8773         if (n == NULL)
8774                 return NULL;
8775         new = funcblock;
8776         funcblock = (char *) funcblock + nodesize[n->type];
8777
8778         switch (n->type) {
8779         case NCMD:
8780                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8781                 new->ncmd.args = copynode(n->ncmd.args);
8782                 new->ncmd.assign = copynode(n->ncmd.assign);
8783                 new->ncmd.linno = n->ncmd.linno;
8784                 break;
8785         case NPIPE:
8786                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8787                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8788                 break;
8789         case NREDIR:
8790         case NBACKGND:
8791         case NSUBSHELL:
8792                 new->nredir.redirect = copynode(n->nredir.redirect);
8793                 new->nredir.n = copynode(n->nredir.n);
8794                 new->nredir.linno = n->nredir.linno;
8795                 break;
8796         case NAND:
8797         case NOR:
8798         case NSEMI:
8799         case NWHILE:
8800         case NUNTIL:
8801                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8802                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8803                 break;
8804         case NIF:
8805                 new->nif.elsepart = copynode(n->nif.elsepart);
8806                 new->nif.ifpart = copynode(n->nif.ifpart);
8807                 new->nif.test = copynode(n->nif.test);
8808                 break;
8809         case NFOR:
8810                 new->nfor.var = nodeckstrdup(n->nfor.var);
8811                 new->nfor.body = copynode(n->nfor.body);
8812                 new->nfor.args = copynode(n->nfor.args);
8813                 new->nfor.linno = n->nfor.linno;
8814                 break;
8815         case NCASE:
8816                 new->ncase.cases = copynode(n->ncase.cases);
8817                 new->ncase.expr = copynode(n->ncase.expr);
8818                 new->ncase.linno = n->ncase.linno;
8819                 break;
8820         case NCLIST:
8821                 new->nclist.body = copynode(n->nclist.body);
8822                 new->nclist.pattern = copynode(n->nclist.pattern);
8823                 new->nclist.next = copynode(n->nclist.next);
8824                 break;
8825         case NDEFUN:
8826                 new->ndefun.body = copynode(n->ndefun.body);
8827                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8828                 new->ndefun.linno = n->ndefun.linno;
8829                 break;
8830         case NARG:
8831                 new->narg.backquote = copynodelist(n->narg.backquote);
8832                 new->narg.text = nodeckstrdup(n->narg.text);
8833                 new->narg.next = copynode(n->narg.next);
8834                 break;
8835         case NTO:
8836 #if BASH_REDIR_OUTPUT
8837         case NTO2:
8838 #endif
8839         case NCLOBBER:
8840         case NFROM:
8841         case NFROMTO:
8842         case NAPPEND:
8843                 new->nfile.fname = copynode(n->nfile.fname);
8844                 new->nfile.fd = n->nfile.fd;
8845                 new->nfile.next = copynode(n->nfile.next);
8846                 break;
8847         case NTOFD:
8848         case NFROMFD:
8849                 new->ndup.vname = copynode(n->ndup.vname);
8850                 new->ndup.dupfd = n->ndup.dupfd;
8851                 new->ndup.fd = n->ndup.fd;
8852                 new->ndup.next = copynode(n->ndup.next);
8853                 break;
8854         case NHERE:
8855         case NXHERE:
8856                 new->nhere.doc = copynode(n->nhere.doc);
8857                 new->nhere.fd = n->nhere.fd;
8858                 new->nhere.next = copynode(n->nhere.next);
8859                 break;
8860         case NNOT:
8861                 new->nnot.com = copynode(n->nnot.com);
8862                 break;
8863         };
8864         new->type = n->type;
8865         return new;
8866 }
8867
8868 /*
8869  * Make a copy of a parse tree.
8870  */
8871 static struct funcnode *
8872 copyfunc(union node *n)
8873 {
8874         struct funcnode *f;
8875         size_t blocksize;
8876
8877         /*funcstringsize = 0;*/
8878         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8879         f = ckzalloc(blocksize /* + funcstringsize */);
8880         funcblock = (char *) f + offsetof(struct funcnode, n);
8881         funcstring_end = (char *) f + blocksize;
8882         copynode(n);
8883         /* f->count = 0; - ckzalloc did it */
8884         return f;
8885 }
8886
8887 /*
8888  * Define a shell function.
8889  */
8890 static void
8891 defun(union node *func)
8892 {
8893         struct cmdentry entry;
8894
8895         INT_OFF;
8896         entry.cmdtype = CMDFUNCTION;
8897         entry.u.func = copyfunc(func);
8898         addcmdentry(func->ndefun.text, &entry);
8899         INT_ON;
8900 }
8901
8902 /* Reasons for skipping commands (see comment on breakcmd routine) */
8903 #define SKIPBREAK      (1 << 0)
8904 #define SKIPCONT       (1 << 1)
8905 #define SKIPFUNC       (1 << 2)
8906 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8907 static int skipcount;           /* number of levels to skip */
8908 static int loopnest;            /* current loop nesting level */
8909 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8910
8911 /* Forward decl way out to parsing code - dotrap needs it */
8912 static int evalstring(char *s, int flags);
8913
8914 /* Called to execute a trap.
8915  * Single callsite - at the end of evaltree().
8916  * If we return non-zero, evaltree raises EXEXIT exception.
8917  *
8918  * Perhaps we should avoid entering new trap handlers
8919  * while we are executing a trap handler. [is it a TODO?]
8920  */
8921 static void
8922 dotrap(void)
8923 {
8924         uint8_t *g;
8925         int sig;
8926         uint8_t last_status;
8927
8928         if (!pending_sig)
8929                 return;
8930
8931         last_status = exitstatus;
8932         pending_sig = 0;
8933         barrier();
8934
8935         TRACE(("dotrap entered\n"));
8936         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8937                 char *p;
8938
8939                 if (!*g)
8940                         continue;
8941
8942                 if (evalskip) {
8943                         pending_sig = sig;
8944                         break;
8945                 }
8946
8947                 p = trap[sig];
8948                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8949                  * don't upset it by resetting gotsig[SIGINT-1] */
8950                 if (sig == SIGINT && !p)
8951                         continue;
8952
8953                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8954                 *g = 0;
8955                 if (!p)
8956                         continue;
8957                 evalstring(p, 0);
8958         }
8959         exitstatus = last_status;
8960         TRACE(("dotrap returns\n"));
8961 }
8962
8963 /* forward declarations - evaluation is fairly recursive business... */
8964 static int evalloop(union node *, int);
8965 static int evalfor(union node *, int);
8966 static int evalcase(union node *, int);
8967 static int evalsubshell(union node *, int);
8968 static void expredir(union node *);
8969 static int evalpipe(union node *, int);
8970 static int evalcommand(union node *, int);
8971 static int evalbltin(const struct builtincmd *, int, char **, int);
8972 static void prehash(union node *);
8973
8974 /*
8975  * Evaluate a parse tree.  The value is left in the global variable
8976  * exitstatus.
8977  */
8978 static int
8979 evaltree(union node *n, int flags)
8980 {
8981         int checkexit = 0;
8982         int (*evalfn)(union node *, int);
8983         int status = 0;
8984
8985         if (n == NULL) {
8986                 TRACE(("evaltree(NULL) called\n"));
8987                 goto out;
8988         }
8989         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8990
8991         dotrap();
8992
8993         switch (n->type) {
8994         default:
8995 #if DEBUG
8996                 out1fmt("Node type = %d\n", n->type);
8997                 fflush_all();
8998                 break;
8999 #endif
9000         case NNOT:
9001                 status = !evaltree(n->nnot.com, EV_TESTED);
9002                 goto setstatus;
9003         case NREDIR:
9004                 errlinno = lineno = n->nredir.linno;
9005                 if (funcline)
9006                         lineno -= funcline - 1;
9007                 expredir(n->nredir.redirect);
9008                 pushredir(n->nredir.redirect);
9009                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9010                 if (!status) {
9011                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9012                 }
9013                 if (n->nredir.redirect)
9014                         popredir(/*drop:*/ 0);
9015                 goto setstatus;
9016         case NCMD:
9017                 evalfn = evalcommand;
9018  checkexit:
9019                 if (eflag && !(flags & EV_TESTED))
9020                         checkexit = ~0;
9021                 goto calleval;
9022         case NFOR:
9023                 evalfn = evalfor;
9024                 goto calleval;
9025         case NWHILE:
9026         case NUNTIL:
9027                 evalfn = evalloop;
9028                 goto calleval;
9029         case NSUBSHELL:
9030         case NBACKGND:
9031                 evalfn = evalsubshell;
9032                 goto checkexit;
9033         case NPIPE:
9034                 evalfn = evalpipe;
9035                 goto checkexit;
9036         case NCASE:
9037                 evalfn = evalcase;
9038                 goto calleval;
9039         case NAND:
9040         case NOR:
9041         case NSEMI: {
9042
9043 #if NAND + 1 != NOR
9044 #error NAND + 1 != NOR
9045 #endif
9046 #if NOR + 1 != NSEMI
9047 #error NOR + 1 != NSEMI
9048 #endif
9049                 unsigned is_or = n->type - NAND;
9050                 status = evaltree(
9051                         n->nbinary.ch1,
9052                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9053                 );
9054                 if ((!status) == is_or || evalskip)
9055                         break;
9056                 n = n->nbinary.ch2;
9057  evaln:
9058                 evalfn = evaltree;
9059  calleval:
9060                 status = evalfn(n, flags);
9061                 goto setstatus;
9062         }
9063         case NIF:
9064                 status = evaltree(n->nif.test, EV_TESTED);
9065                 if (evalskip)
9066                         break;
9067                 if (!status) {
9068                         n = n->nif.ifpart;
9069                         goto evaln;
9070                 }
9071                 if (n->nif.elsepart) {
9072                         n = n->nif.elsepart;
9073                         goto evaln;
9074                 }
9075                 status = 0;
9076                 goto setstatus;
9077         case NDEFUN:
9078                 defun(n);
9079                 /* Not necessary. To test it:
9080                  * "false; f() { qwerty; }; echo $?" should print 0.
9081                  */
9082                 /* status = 0; */
9083  setstatus:
9084                 exitstatus = status;
9085                 break;
9086         }
9087  out:
9088         /* Order of checks below is important:
9089          * signal handlers trigger before exit caused by "set -e".
9090          */
9091         dotrap();
9092
9093         if (checkexit & status)
9094                 raise_exception(EXEXIT);
9095         if (flags & EV_EXIT)
9096                 raise_exception(EXEXIT);
9097
9098         TRACE(("leaving evaltree (no interrupts)\n"));
9099         return exitstatus;
9100 }
9101
9102 static int
9103 skiploop(void)
9104 {
9105         int skip = evalskip;
9106
9107         switch (skip) {
9108         case 0:
9109                 break;
9110         case SKIPBREAK:
9111         case SKIPCONT:
9112                 if (--skipcount <= 0) {
9113                         evalskip = 0;
9114                         break;
9115                 }
9116                 skip = SKIPBREAK;
9117                 break;
9118         }
9119         return skip;
9120 }
9121
9122 static int
9123 evalloop(union node *n, int flags)
9124 {
9125         int skip;
9126         int status;
9127
9128         loopnest++;
9129         status = 0;
9130         flags &= EV_TESTED;
9131         do {
9132                 int i;
9133
9134                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9135                 skip = skiploop();
9136                 if (skip == SKIPFUNC)
9137                         status = i;
9138                 if (skip)
9139                         continue;
9140                 if (n->type != NWHILE)
9141                         i = !i;
9142                 if (i != 0)
9143                         break;
9144                 status = evaltree(n->nbinary.ch2, flags);
9145                 skip = skiploop();
9146         } while (!(skip & ~SKIPCONT));
9147         loopnest--;
9148
9149         return status;
9150 }
9151
9152 static int
9153 evalfor(union node *n, int flags)
9154 {
9155         struct arglist arglist;
9156         union node *argp;
9157         struct strlist *sp;
9158         struct stackmark smark;
9159         int status = 0;
9160
9161         errlinno = lineno = n->ncase.linno;
9162         if (funcline)
9163                 lineno -= funcline - 1;
9164
9165         setstackmark(&smark);
9166         arglist.list = NULL;
9167         arglist.lastp = &arglist.list;
9168         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9169                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9170         }
9171         *arglist.lastp = NULL;
9172
9173         loopnest++;
9174         flags &= EV_TESTED;
9175         for (sp = arglist.list; sp; sp = sp->next) {
9176                 setvar0(n->nfor.var, sp->text);
9177                 status = evaltree(n->nfor.body, flags);
9178                 if (skiploop() & ~SKIPCONT)
9179                         break;
9180         }
9181         loopnest--;
9182         popstackmark(&smark);
9183
9184         return status;
9185 }
9186
9187 static int
9188 evalcase(union node *n, int flags)
9189 {
9190         union node *cp;
9191         union node *patp;
9192         struct arglist arglist;
9193         struct stackmark smark;
9194         int status = 0;
9195
9196         errlinno = lineno = n->ncase.linno;
9197         if (funcline)
9198                 lineno -= funcline - 1;
9199
9200         setstackmark(&smark);
9201         arglist.list = NULL;
9202         arglist.lastp = &arglist.list;
9203         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9204         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9205                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9206                         if (casematch(patp, arglist.list->text)) {
9207                                 /* Ensure body is non-empty as otherwise
9208                                  * EV_EXIT may prevent us from setting the
9209                                  * exit status.
9210                                  */
9211                                 if (evalskip == 0 && cp->nclist.body) {
9212                                         status = evaltree(cp->nclist.body, flags);
9213                                 }
9214                                 goto out;
9215                         }
9216                 }
9217         }
9218  out:
9219         popstackmark(&smark);
9220
9221         return status;
9222 }
9223
9224 /*
9225  * Kick off a subshell to evaluate a tree.
9226  */
9227 static int
9228 evalsubshell(union node *n, int flags)
9229 {
9230         struct job *jp;
9231         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9232         int status;
9233
9234         errlinno = lineno = n->nredir.linno;
9235         if (funcline)
9236                 lineno -= funcline - 1;
9237
9238         expredir(n->nredir.redirect);
9239         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9240                 goto nofork;
9241         INT_OFF;
9242         if (backgnd == FORK_FG)
9243                 get_tty_state();
9244         jp = makejob(/*n,*/ 1);
9245         if (forkshell(jp, n, backgnd) == 0) {
9246                 /* child */
9247                 INT_ON;
9248                 flags |= EV_EXIT;
9249                 if (backgnd)
9250                         flags &= ~EV_TESTED;
9251  nofork:
9252                 redirect(n->nredir.redirect, 0);
9253                 evaltreenr(n->nredir.n, flags);
9254                 /* never returns */
9255         }
9256         /* parent */
9257         status = 0;
9258         if (backgnd == FORK_FG)
9259                 status = waitforjob(jp);
9260         INT_ON;
9261         return status;
9262 }
9263
9264 /*
9265  * Compute the names of the files in a redirection list.
9266  */
9267 static void fixredir(union node *, const char *, int);
9268 static void
9269 expredir(union node *n)
9270 {
9271         union node *redir;
9272
9273         for (redir = n; redir; redir = redir->nfile.next) {
9274                 struct arglist fn;
9275
9276                 fn.list = NULL;
9277                 fn.lastp = &fn.list;
9278                 switch (redir->type) {
9279                 case NFROMTO:
9280                 case NFROM:
9281                 case NTO:
9282 #if BASH_REDIR_OUTPUT
9283                 case NTO2:
9284 #endif
9285                 case NCLOBBER:
9286                 case NAPPEND:
9287                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9288                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9289 #if BASH_REDIR_OUTPUT
9290  store_expfname:
9291 #endif
9292 #if 0
9293 // By the design of stack allocator, the loop of this kind:
9294 //      while true; do while true; do break; done </dev/null; done
9295 // will look like a memory leak: ash plans to free expfname's
9296 // of "/dev/null" as soon as it finishes running the loop
9297 // (in this case, never).
9298 // This "fix" is wrong:
9299                         if (redir->nfile.expfname)
9300                                 stunalloc(redir->nfile.expfname);
9301 // It results in corrupted state of stacked allocations.
9302 #endif
9303                         redir->nfile.expfname = fn.list->text;
9304                         break;
9305                 case NFROMFD:
9306                 case NTOFD: /* >& */
9307                         if (redir->ndup.vname) {
9308                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9309                                 if (fn.list == NULL)
9310                                         ash_msg_and_raise_error("redir error");
9311 #if BASH_REDIR_OUTPUT
9312 //FIXME: we used expandarg with different args!
9313                                 if (!isdigit_str9(fn.list->text)) {
9314                                         /* >&file, not >&fd */
9315                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9316                                                 ash_msg_and_raise_error("redir error");
9317                                         redir->type = NTO2;
9318                                         goto store_expfname;
9319                                 }
9320 #endif
9321                                 fixredir(redir, fn.list->text, 1);
9322                         }
9323                         break;
9324                 }
9325         }
9326 }
9327
9328 /*
9329  * Evaluate a pipeline.  All the processes in the pipeline are children
9330  * of the process creating the pipeline.  (This differs from some versions
9331  * of the shell, which make the last process in a pipeline the parent
9332  * of all the rest.)
9333  */
9334 static int
9335 evalpipe(union node *n, int flags)
9336 {
9337         struct job *jp;
9338         struct nodelist *lp;
9339         int pipelen;
9340         int prevfd;
9341         int pip[2];
9342         int status = 0;
9343
9344         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9345         pipelen = 0;
9346         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9347                 pipelen++;
9348         flags |= EV_EXIT;
9349         INT_OFF;
9350         if (n->npipe.pipe_backgnd == 0)
9351                 get_tty_state();
9352         jp = makejob(/*n,*/ pipelen);
9353         prevfd = -1;
9354         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9355                 prehash(lp->n);
9356                 pip[1] = -1;
9357                 if (lp->next) {
9358                         if (pipe(pip) < 0) {
9359                                 close(prevfd);
9360                                 ash_msg_and_raise_perror("can't create pipe");
9361                         }
9362                 }
9363                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9364                         /* child */
9365                         INT_ON;
9366                         if (pip[1] >= 0) {
9367                                 close(pip[0]);
9368                         }
9369                         if (prevfd > 0) {
9370                                 dup2(prevfd, 0);
9371                                 close(prevfd);
9372                         }
9373                         if (pip[1] > 1) {
9374                                 dup2(pip[1], 1);
9375                                 close(pip[1]);
9376                         }
9377                         evaltreenr(lp->n, flags);
9378                         /* never returns */
9379                 }
9380                 /* parent */
9381                 if (prevfd >= 0)
9382                         close(prevfd);
9383                 prevfd = pip[0];
9384                 /* Don't want to trigger debugging */
9385                 if (pip[1] != -1)
9386                         close(pip[1]);
9387         }
9388         if (n->npipe.pipe_backgnd == 0) {
9389                 status = waitforjob(jp);
9390                 TRACE(("evalpipe:  job done exit status %d\n", status));
9391         }
9392         INT_ON;
9393
9394         return status;
9395 }
9396
9397 /*
9398  * Controls whether the shell is interactive or not.
9399  */
9400 static void
9401 setinteractive(int on)
9402 {
9403         static smallint is_interactive;
9404
9405         if (++on == is_interactive)
9406                 return;
9407         is_interactive = on;
9408         setsignal(SIGINT);
9409         setsignal(SIGQUIT);
9410         setsignal(SIGTERM);
9411 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9412         if (is_interactive > 1) {
9413                 /* Looks like they want an interactive shell */
9414                 static smallint did_banner;
9415
9416                 if (!did_banner) {
9417                         /* note: ash and hush share this string */
9418                         out1fmt("\n\n%s %s\n"
9419                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9420                                 "\n",
9421                                 bb_banner,
9422                                 "built-in shell (ash)"
9423                         );
9424                         did_banner = 1;
9425                 }
9426         }
9427 #endif
9428 }
9429
9430 static void
9431 optschanged(void)
9432 {
9433 #if DEBUG
9434         opentrace();
9435 #endif
9436         setinteractive(iflag);
9437         setjobctl(mflag);
9438 #if ENABLE_FEATURE_EDITING_VI
9439         if (viflag)
9440                 line_input_state->flags |= VI_MODE;
9441         else
9442                 line_input_state->flags &= ~VI_MODE;
9443 #else
9444         viflag = 0; /* forcibly keep the option off */
9445 #endif
9446 }
9447
9448 struct localvar_list {
9449         struct localvar_list *next;
9450         struct localvar *lv;
9451 };
9452
9453 static struct localvar_list *localvar_stack;
9454
9455 /*
9456  * Called after a function returns.
9457  * Interrupts must be off.
9458  */
9459 static void
9460 poplocalvars(int keep)
9461 {
9462         struct localvar_list *ll;
9463         struct localvar *lvp, *next;
9464         struct var *vp;
9465
9466         INT_OFF;
9467         ll = localvar_stack;
9468         localvar_stack = ll->next;
9469
9470         next = ll->lv;
9471         free(ll);
9472
9473         while ((lvp = next) != NULL) {
9474                 next = lvp->next;
9475                 vp = lvp->vp;
9476                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9477                 if (keep) {
9478                         int bits = VSTRFIXED;
9479
9480                         if (lvp->flags != VUNSET) {
9481                                 if (vp->var_text == lvp->text)
9482                                         bits |= VTEXTFIXED;
9483                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9484                                         free((char*)lvp->text);
9485                         }
9486
9487                         vp->flags &= ~bits;
9488                         vp->flags |= (lvp->flags & bits);
9489
9490                         if ((vp->flags &
9491                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9492                                 unsetvar(vp->var_text);
9493                 } else if (vp == NULL) {        /* $- saved */
9494                         memcpy(optlist, lvp->text, sizeof(optlist));
9495                         free((char*)lvp->text);
9496                         optschanged();
9497                 } else if (lvp->flags == VUNSET) {
9498                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9499                         unsetvar(vp->var_text);
9500                 } else {
9501                         if (vp->var_func)
9502                                 vp->var_func(var_end(lvp->text));
9503                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9504                                 free((char*)vp->var_text);
9505                         vp->flags = lvp->flags;
9506                         vp->var_text = lvp->text;
9507                 }
9508                 free(lvp);
9509         }
9510         INT_ON;
9511 }
9512
9513 /*
9514  * Create a new localvar environment.
9515  */
9516 static struct localvar_list *
9517 pushlocalvars(void)
9518 {
9519         struct localvar_list *ll;
9520
9521         INT_OFF;
9522         ll = ckzalloc(sizeof(*ll));
9523         /*ll->lv = NULL; - zalloc did it */
9524         ll->next = localvar_stack;
9525         localvar_stack = ll;
9526         INT_ON;
9527
9528         return ll->next;
9529 }
9530
9531 static void
9532 unwindlocalvars(struct localvar_list *stop)
9533 {
9534         while (localvar_stack != stop)
9535                 poplocalvars(0);
9536 }
9537
9538 static int
9539 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9540 {
9541         volatile struct shparam saveparam;
9542         struct jmploc *volatile savehandler;
9543         struct jmploc jmploc;
9544         int e;
9545         int savefuncline;
9546
9547         saveparam = shellparam;
9548         savefuncline = funcline;
9549         savehandler = exception_handler;
9550         e = setjmp(jmploc.loc);
9551         if (e) {
9552                 goto funcdone;
9553         }
9554         INT_OFF;
9555         exception_handler = &jmploc;
9556         shellparam.malloced = 0;
9557         func->count++;
9558         funcline = func->n.ndefun.linno;
9559         INT_ON;
9560         shellparam.nparam = argc - 1;
9561         shellparam.p = argv + 1;
9562 #if ENABLE_ASH_GETOPTS
9563         shellparam.optind = 1;
9564         shellparam.optoff = -1;
9565 #endif
9566         pushlocalvars();
9567         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9568         poplocalvars(0);
9569  funcdone:
9570         INT_OFF;
9571         funcline = savefuncline;
9572         freefunc(func);
9573         freeparam(&shellparam);
9574         shellparam = saveparam;
9575         exception_handler = savehandler;
9576         INT_ON;
9577         evalskip &= ~SKIPFUNC;
9578         return e;
9579 }
9580
9581 /*
9582  * Make a variable a local variable.  When a variable is made local, it's
9583  * value and flags are saved in a localvar structure.  The saved values
9584  * will be restored when the shell function returns.  We handle the name
9585  * "-" as a special case: it makes changes to "set +-options" local
9586  * (options will be restored on return from the function).
9587  */
9588 static void
9589 mklocal(char *name)
9590 {
9591         struct localvar *lvp;
9592         struct var **vpp;
9593         struct var *vp;
9594         char *eq = strchr(name, '=');
9595
9596         INT_OFF;
9597         /* Cater for duplicate "local". Examples:
9598          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9599          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9600          */
9601         lvp = localvar_stack->lv;
9602         while (lvp) {
9603                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9604                         if (eq)
9605                                 setvareq(name, 0);
9606                         /* else:
9607                          * it's a duplicate "local VAR" declaration, do nothing
9608                          */
9609                         goto ret;
9610                 }
9611                 lvp = lvp->next;
9612         }
9613
9614         lvp = ckzalloc(sizeof(*lvp));
9615         if (LONE_DASH(name)) {
9616                 char *p;
9617                 p = ckmalloc(sizeof(optlist));
9618                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9619                 vp = NULL;
9620         } else {
9621                 vpp = hashvar(name);
9622                 vp = *findvar(vpp, name);
9623                 if (vp == NULL) {
9624                         /* variable did not exist yet */
9625                         if (eq)
9626                                 vp = setvareq(name, VSTRFIXED);
9627                         else
9628                                 vp = setvar(name, NULL, VSTRFIXED);
9629                         lvp->flags = VUNSET;
9630                 } else {
9631                         lvp->text = vp->var_text;
9632                         lvp->flags = vp->flags;
9633                         /* make sure neither "struct var" nor string gets freed
9634                          * during (un)setting:
9635                          */
9636                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9637                         if (eq)
9638                                 setvareq(name, 0);
9639                         else
9640                                 /* "local VAR" unsets VAR: */
9641                                 setvar0(name, NULL);
9642                 }
9643         }
9644         lvp->vp = vp;
9645         lvp->next = localvar_stack->lv;
9646         localvar_stack->lv = lvp;
9647  ret:
9648         INT_ON;
9649 }
9650
9651 /*
9652  * The "local" command.
9653  */
9654 static int FAST_FUNC
9655 localcmd(int argc UNUSED_PARAM, char **argv)
9656 {
9657         char *name;
9658
9659         if (!localvar_stack)
9660                 ash_msg_and_raise_error("not in a function");
9661
9662         argv = argptr;
9663         while ((name = *argv++) != NULL) {
9664                 mklocal(name);
9665         }
9666         return 0;
9667 }
9668
9669 static int FAST_FUNC
9670 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9671 {
9672         return 1;
9673 }
9674
9675 static int FAST_FUNC
9676 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9677 {
9678         return 0;
9679 }
9680
9681 static int FAST_FUNC
9682 execcmd(int argc UNUSED_PARAM, char **argv)
9683 {
9684         optionarg = NULL;
9685         while (nextopt("a:") != '\0')
9686                 /* nextopt() sets optionarg to "-a ARGV0" */;
9687
9688         argv = argptr;
9689         if (argv[0]) {
9690                 char *prog;
9691
9692                 iflag = 0;              /* exit on error */
9693                 mflag = 0;
9694                 optschanged();
9695                 /* We should set up signals for "exec CMD"
9696                  * the same way as for "CMD" without "exec".
9697                  * But optschanged->setinteractive->setsignal
9698                  * still thought we are a root shell. Therefore, for example,
9699                  * SIGQUIT is still set to IGN. Fix it:
9700                  */
9701                 shlvl++;
9702                 setsignal(SIGQUIT);
9703                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9704                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9705                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9706
9707                 prog = argv[0];
9708                 if (optionarg)
9709                         argv[0] = optionarg;
9710                 shellexec(prog, argv, pathval(), 0);
9711                 /* NOTREACHED */
9712         }
9713         return 0;
9714 }
9715
9716 /*
9717  * The return command.
9718  */
9719 static int FAST_FUNC
9720 returncmd(int argc UNUSED_PARAM, char **argv)
9721 {
9722         /*
9723          * If called outside a function, do what ksh does;
9724          * skip the rest of the file.
9725          */
9726         evalskip = SKIPFUNC;
9727         return argv[1] ? number(argv[1]) : exitstatus;
9728 }
9729
9730 /* Forward declarations for builtintab[] */
9731 static int breakcmd(int, char **) FAST_FUNC;
9732 static int dotcmd(int, char **) FAST_FUNC;
9733 static int evalcmd(int, char **, int) FAST_FUNC;
9734 static int exitcmd(int, char **) FAST_FUNC;
9735 static int exportcmd(int, char **) FAST_FUNC;
9736 #if ENABLE_ASH_GETOPTS
9737 static int getoptscmd(int, char **) FAST_FUNC;
9738 #endif
9739 #if ENABLE_ASH_HELP
9740 static int helpcmd(int, char **) FAST_FUNC;
9741 #endif
9742 #if MAX_HISTORY
9743 static int historycmd(int, char **) FAST_FUNC;
9744 #endif
9745 #if ENABLE_FEATURE_SH_MATH
9746 static int letcmd(int, char **) FAST_FUNC;
9747 #endif
9748 static int readcmd(int, char **) FAST_FUNC;
9749 static int setcmd(int, char **) FAST_FUNC;
9750 static int shiftcmd(int, char **) FAST_FUNC;
9751 static int timescmd(int, char **) FAST_FUNC;
9752 static int trapcmd(int, char **) FAST_FUNC;
9753 static int umaskcmd(int, char **) FAST_FUNC;
9754 static int unsetcmd(int, char **) FAST_FUNC;
9755 static int ulimitcmd(int, char **) FAST_FUNC;
9756
9757 #define BUILTIN_NOSPEC          "0"
9758 #define BUILTIN_SPECIAL         "1"
9759 #define BUILTIN_REGULAR         "2"
9760 #define BUILTIN_SPEC_REG        "3"
9761 #define BUILTIN_ASSIGN          "4"
9762 #define BUILTIN_SPEC_ASSG       "5"
9763 #define BUILTIN_REG_ASSG        "6"
9764 #define BUILTIN_SPEC_REG_ASSG   "7"
9765
9766 /* Stubs for calling non-FAST_FUNC's */
9767 #if ENABLE_ASH_ECHO
9768 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9769 #endif
9770 #if ENABLE_ASH_PRINTF
9771 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9772 #endif
9773 #if ENABLE_ASH_TEST || BASH_TEST2
9774 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9775 #endif
9776
9777 /* Keep these in proper order since it is searched via bsearch() */
9778 static const struct builtincmd builtintab[] = {
9779         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9780         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9781 #if ENABLE_ASH_TEST
9782         { BUILTIN_REGULAR       "["       , testcmd    },
9783 #endif
9784 #if BASH_TEST2
9785         { BUILTIN_REGULAR       "[["      , testcmd    },
9786 #endif
9787 #if ENABLE_ASH_ALIAS
9788         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9789 #endif
9790 #if JOBS
9791         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9792 #endif
9793         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9794         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9795         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9796 #if ENABLE_ASH_CMDCMD
9797         { BUILTIN_REGULAR       "command" , commandcmd },
9798 #endif
9799         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9800 #if ENABLE_ASH_ECHO
9801         { BUILTIN_REGULAR       "echo"    , echocmd    },
9802 #endif
9803         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9804         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9805         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9806         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9807         { BUILTIN_REGULAR       "false"   , falsecmd   },
9808 #if JOBS
9809         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9810 #endif
9811 #if ENABLE_ASH_GETOPTS
9812         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9813 #endif
9814         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9815 #if ENABLE_ASH_HELP
9816         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9817 #endif
9818 #if MAX_HISTORY
9819         { BUILTIN_NOSPEC        "history" , historycmd },
9820 #endif
9821 #if JOBS
9822         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9823         { BUILTIN_REGULAR       "kill"    , killcmd    },
9824 #endif
9825 #if ENABLE_FEATURE_SH_MATH
9826         { BUILTIN_NOSPEC        "let"     , letcmd     },
9827 #endif
9828         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9829 #if ENABLE_ASH_PRINTF
9830         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9831 #endif
9832         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9833         { BUILTIN_REGULAR       "read"    , readcmd    },
9834         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9835         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9836         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9837         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9838 #if BASH_SOURCE
9839         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9840 #endif
9841 #if ENABLE_ASH_TEST
9842         { BUILTIN_REGULAR       "test"    , testcmd    },
9843 #endif
9844         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9845         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9846         { BUILTIN_REGULAR       "true"    , truecmd    },
9847         { BUILTIN_NOSPEC        "type"    , typecmd    },
9848         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9849         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9850 #if ENABLE_ASH_ALIAS
9851         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9852 #endif
9853         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9854         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9855 };
9856
9857 /* Should match the above table! */
9858 #define COMMANDCMD (builtintab + \
9859         /* . : */       2 + \
9860         /* [ */         1 * ENABLE_ASH_TEST + \
9861         /* [[ */        1 * BASH_TEST2 + \
9862         /* alias */     1 * ENABLE_ASH_ALIAS + \
9863         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9864         /* break cd cddir  */   3)
9865 #define EVALCMD (COMMANDCMD + \
9866         /* command */   1 * ENABLE_ASH_CMDCMD + \
9867         /* continue */  1 + \
9868         /* echo */      1 * ENABLE_ASH_ECHO + \
9869         0)
9870 #define EXECCMD (EVALCMD + \
9871         /* eval */      1)
9872
9873 /*
9874  * Search the table of builtin commands.
9875  */
9876 static int
9877 pstrcmp1(const void *a, const void *b)
9878 {
9879         return strcmp((char*)a, *(char**)b + 1);
9880 }
9881 static struct builtincmd *
9882 find_builtin(const char *name)
9883 {
9884         struct builtincmd *bp;
9885
9886         bp = bsearch(
9887                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9888                 pstrcmp1
9889         );
9890         return bp;
9891 }
9892
9893 /*
9894  * Execute a simple command.
9895  */
9896 static int
9897 isassignment(const char *p)
9898 {
9899         const char *q = endofname(p);
9900         if (p == q)
9901                 return 0;
9902         return *q == '=';
9903 }
9904 static int FAST_FUNC
9905 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9906 {
9907         /* Preserve exitstatus of a previous possible redirection
9908          * as POSIX mandates */
9909         return back_exitstatus;
9910 }
9911 static int
9912 evalcommand(union node *cmd, int flags)
9913 {
9914         static const struct builtincmd null_bltin = {
9915                 "\0\0", bltincmd /* why three NULs? */
9916         };
9917         struct localvar_list *localvar_stop;
9918         struct redirtab *redir_stop;
9919         struct stackmark smark;
9920         union node *argp;
9921         struct arglist arglist;
9922         struct arglist varlist;
9923         char **argv;
9924         int argc;
9925         const struct strlist *sp;
9926         struct cmdentry cmdentry;
9927         struct job *jp;
9928         char *lastarg;
9929         const char *path;
9930         int spclbltin;
9931         int status;
9932         char **nargv;
9933         smallint cmd_is_exec;
9934
9935         errlinno = lineno = cmd->ncmd.linno;
9936         if (funcline)
9937                 lineno -= funcline - 1;
9938
9939         /* First expand the arguments. */
9940         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9941         setstackmark(&smark);
9942         localvar_stop = pushlocalvars();
9943         back_exitstatus = 0;
9944
9945         cmdentry.cmdtype = CMDBUILTIN;
9946         cmdentry.u.cmd = &null_bltin;
9947         varlist.lastp = &varlist.list;
9948         *varlist.lastp = NULL;
9949         arglist.lastp = &arglist.list;
9950         *arglist.lastp = NULL;
9951
9952         argc = 0;
9953         if (cmd->ncmd.args) {
9954                 struct builtincmd *bcmd;
9955                 smallint pseudovarflag;
9956
9957                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9958                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9959
9960                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9961                         struct strlist **spp;
9962
9963                         spp = arglist.lastp;
9964                         if (pseudovarflag && isassignment(argp->narg.text))
9965                                 expandarg(argp, &arglist, EXP_VARTILDE);
9966                         else
9967                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9968
9969                         for (sp = *spp; sp; sp = sp->next)
9970                                 argc++;
9971                 }
9972         }
9973
9974         /* Reserve one extra spot at the front for shellexec. */
9975         nargv = stalloc(sizeof(char *) * (argc + 2));
9976         argv = ++nargv;
9977         for (sp = arglist.list; sp; sp = sp->next) {
9978                 TRACE(("evalcommand arg: %s\n", sp->text));
9979                 *nargv++ = sp->text;
9980         }
9981         *nargv = NULL;
9982
9983         lastarg = NULL;
9984         if (iflag && funcline == 0 && argc > 0)
9985                 lastarg = nargv[-1];
9986
9987         expredir(cmd->ncmd.redirect);
9988         redir_stop = pushredir(cmd->ncmd.redirect);
9989         preverrout_fd = 2;
9990         if (BASH_XTRACEFD && xflag) {
9991                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9992                  * we do not emulate this. We only use its value.
9993                  */
9994                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9995                 if (xtracefd && is_number(xtracefd))
9996                         preverrout_fd = atoi(xtracefd);
9997
9998         }
9999         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10000
10001         path = vpath.var_text;
10002         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10003                 struct strlist **spp;
10004                 char *p;
10005
10006                 spp = varlist.lastp;
10007                 expandarg(argp, &varlist, EXP_VARTILDE);
10008
10009                 mklocal((*spp)->text);
10010
10011                 /*
10012                  * Modify the command lookup path, if a PATH= assignment
10013                  * is present
10014                  */
10015                 p = (*spp)->text;
10016                 if (varcmp(p, path) == 0)
10017                         path = p;
10018         }
10019
10020         /* Print the command if xflag is set. */
10021         if (xflag) {
10022                 const char *pfx = "";
10023
10024                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10025
10026                 sp = varlist.list;
10027                 while (sp) {
10028                         char *varval = sp->text;
10029                         char *eq = strchrnul(varval, '=');
10030                         if (*eq)
10031                                 eq++;
10032                         fdprintf(preverrout_fd, "%s%.*s%s",
10033                                 pfx,
10034                                 (int)(eq - varval), varval,
10035                                 maybe_single_quote(eq)
10036                         );
10037                         sp = sp->next;
10038                         pfx = " ";
10039                 }
10040
10041                 sp = arglist.list;
10042                 while (sp) {
10043                         fdprintf(preverrout_fd, "%s%s",
10044                                 pfx,
10045                                 /* always quote if matches reserved word: */
10046                                 findkwd(sp->text)
10047                                 ? single_quote(sp->text)
10048                                 : maybe_single_quote(sp->text)
10049                         );
10050                         sp = sp->next;
10051                         pfx = " ";
10052                 }
10053                 safe_write(preverrout_fd, "\n", 1);
10054         }
10055
10056         cmd_is_exec = 0;
10057         spclbltin = -1;
10058
10059         /* Now locate the command. */
10060         if (argc) {
10061                 int cmd_flag = DO_ERR;
10062 #if ENABLE_ASH_CMDCMD
10063                 const char *oldpath = path + 5;
10064 #endif
10065                 path += 5;
10066                 for (;;) {
10067                         find_command(argv[0], &cmdentry, cmd_flag, path);
10068                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10069                                 flush_stdout_stderr();
10070                                 status = 127;
10071                                 goto bail;
10072                         }
10073
10074                         /* implement bltin and command here */
10075                         if (cmdentry.cmdtype != CMDBUILTIN)
10076                                 break;
10077                         if (spclbltin < 0)
10078                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10079                         if (cmdentry.u.cmd == EXECCMD)
10080                                 cmd_is_exec = 1;
10081 #if ENABLE_ASH_CMDCMD
10082                         if (cmdentry.u.cmd == COMMANDCMD) {
10083                                 path = oldpath;
10084                                 nargv = parse_command_args(argv, &path);
10085                                 if (!nargv)
10086                                         break;
10087                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10088                                  * nargv => "PROG". path is updated if -p.
10089                                  */
10090                                 argc -= nargv - argv;
10091                                 argv = nargv;
10092                                 cmd_flag |= DO_NOFUNC;
10093                         } else
10094 #endif
10095                                 break;
10096                 }
10097         }
10098
10099         if (status) {
10100  bail:
10101                 exitstatus = status;
10102
10103                 /* We have a redirection error. */
10104                 if (spclbltin > 0)
10105                         raise_exception(EXERROR);
10106
10107                 goto out;
10108         }
10109
10110         /* Execute the command. */
10111         switch (cmdentry.cmdtype) {
10112         default: {
10113
10114 #if ENABLE_FEATURE_SH_STANDALONE \
10115  && ENABLE_FEATURE_SH_NOFORK \
10116  && NUM_APPLETS > 1
10117 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10118  *     around run_nofork_applet() call.
10119  * (2) Should this check also be done in forkshell()?
10120  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10121  */
10122                 /* find_command() encodes applet_no as (-2 - applet_no) */
10123                 int applet_no = (- cmdentry.u.index - 2);
10124                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10125                         char **sv_environ;
10126
10127                         INT_OFF;
10128                         sv_environ = environ;
10129                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10130                         /*
10131                          * Run <applet>_main().
10132                          * Signals (^C) can't interrupt here.
10133                          * Otherwise we can mangle stdio or malloc internal state.
10134                          * This makes applets which can run for a long time
10135                          * and/or wait for user input ineligible for NOFORK:
10136                          * for example, "yes" or "rm" (rm -i waits for input).
10137                          */
10138                         status = run_nofork_applet(applet_no, argv);
10139                         environ = sv_environ;
10140                         /*
10141                          * Try enabling NOFORK for "yes" applet.
10142                          * ^C _will_ stop it (write returns EINTR),
10143                          * but this causes stdout FILE to be stuck
10144                          * and needing clearerr(). What if other applets
10145                          * also can get EINTRs? Do we need to switch
10146                          * our signals to SA_RESTART?
10147                          */
10148                         /*clearerr(stdout);*/
10149                         INT_ON;
10150                         break;
10151                 }
10152 #endif
10153                 /* Can we avoid forking? For example, very last command
10154                  * in a script or a subshell does not need forking,
10155                  * we can just exec it.
10156                  */
10157                 if (!(flags & EV_EXIT) || may_have_traps) {
10158                         /* No, forking off a child is necessary */
10159                         INT_OFF;
10160                         get_tty_state();
10161                         jp = makejob(/*cmd,*/ 1);
10162                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10163                                 /* parent */
10164                                 status = waitforjob(jp);
10165                                 INT_ON;
10166                                 TRACE(("forked child exited with %d\n", status));
10167                                 break;
10168                         }
10169                         /* child */
10170                         FORCE_INT_ON;
10171                         /* fall through to exec'ing external program */
10172                 }
10173                 listsetvar(varlist.list, VEXPORT|VSTACK);
10174                 shellexec(argv[0], argv, path, cmdentry.u.index);
10175                 /* NOTREACHED */
10176         } /* default */
10177         case CMDBUILTIN:
10178                 if (spclbltin > 0 || argc == 0) {
10179                         poplocalvars(1);
10180                         if (cmd_is_exec && argc > 1)
10181                                 listsetvar(varlist.list, VEXPORT);
10182                 }
10183
10184                 /* Tight loop with builtins only:
10185                  * "while kill -0 $child; do true; done"
10186                  * will never exit even if $child died, unless we do this
10187                  * to reap the zombie and make kill detect that it's gone: */
10188                 dowait(DOWAIT_NONBLOCK, NULL);
10189
10190                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10191                         if (exception_type == EXERROR && spclbltin <= 0) {
10192                                 FORCE_INT_ON;
10193                                 goto readstatus;
10194                         }
10195  raise:
10196                         longjmp(exception_handler->loc, 1);
10197                 }
10198                 goto readstatus;
10199
10200         case CMDFUNCTION:
10201                 poplocalvars(1);
10202                 /* See above for the rationale */
10203                 dowait(DOWAIT_NONBLOCK, NULL);
10204                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10205                         goto raise;
10206  readstatus:
10207                 status = exitstatus;
10208                 break;
10209         } /* switch */
10210
10211  out:
10212         if (cmd->ncmd.redirect)
10213                 popredir(/*drop:*/ cmd_is_exec);
10214         unwindredir(redir_stop);
10215         unwindlocalvars(localvar_stop);
10216         if (lastarg) {
10217                 /* dsl: I think this is intended to be used to support
10218                  * '_' in 'vi' command mode during line editing...
10219                  * However I implemented that within libedit itself.
10220                  */
10221                 setvar0("_", lastarg);
10222         }
10223         popstackmark(&smark);
10224
10225         return status;
10226 }
10227
10228 static int
10229 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10230 {
10231         char *volatile savecmdname;
10232         struct jmploc *volatile savehandler;
10233         struct jmploc jmploc;
10234         int status;
10235         int i;
10236
10237         savecmdname = commandname;
10238         savehandler = exception_handler;
10239         i = setjmp(jmploc.loc);
10240         if (i)
10241                 goto cmddone;
10242         exception_handler = &jmploc;
10243         commandname = argv[0];
10244         argptr = argv + 1;
10245         optptr = NULL;                  /* initialize nextopt */
10246         if (cmd == EVALCMD)
10247                 status = evalcmd(argc, argv, flags);
10248         else
10249                 status = (*cmd->builtin)(argc, argv);
10250         flush_stdout_stderr();
10251         status |= ferror(stdout);
10252         exitstatus = status;
10253  cmddone:
10254         clearerr(stdout);
10255         commandname = savecmdname;
10256         exception_handler = savehandler;
10257
10258         return i;
10259 }
10260
10261 static int
10262 goodname(const char *p)
10263 {
10264         return endofname(p)[0] == '\0';
10265 }
10266
10267
10268 /*
10269  * Search for a command.  This is called before we fork so that the
10270  * location of the command will be available in the parent as well as
10271  * the child.  The check for "goodname" is an overly conservative
10272  * check that the name will not be subject to expansion.
10273  */
10274 static void
10275 prehash(union node *n)
10276 {
10277         struct cmdentry entry;
10278
10279         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10280                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10281 }
10282
10283
10284 /* ============ Builtin commands
10285  *
10286  * Builtin commands whose functions are closely tied to evaluation
10287  * are implemented here.
10288  */
10289
10290 /*
10291  * Handle break and continue commands.  Break, continue, and return are
10292  * all handled by setting the evalskip flag.  The evaluation routines
10293  * above all check this flag, and if it is set they start skipping
10294  * commands rather than executing them.  The variable skipcount is
10295  * the number of loops to break/continue, or the number of function
10296  * levels to return.  (The latter is always 1.)  It should probably
10297  * be an error to break out of more loops than exist, but it isn't
10298  * in the standard shell so we don't make it one here.
10299  */
10300 static int FAST_FUNC
10301 breakcmd(int argc UNUSED_PARAM, char **argv)
10302 {
10303         int n = argv[1] ? number(argv[1]) : 1;
10304
10305         if (n <= 0)
10306                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10307         if (n > loopnest)
10308                 n = loopnest;
10309         if (n > 0) {
10310                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10311                 skipcount = n;
10312         }
10313         return 0;
10314 }
10315
10316
10317 /*
10318  * This implements the input routines used by the parser.
10319  */
10320
10321 enum {
10322         INPUT_PUSH_FILE = 1,
10323         INPUT_NOFILE_OK = 2,
10324 };
10325
10326 static smallint checkkwd;
10327 /* values of checkkwd variable */
10328 #define CHKALIAS        0x1
10329 #define CHKKWD          0x2
10330 #define CHKNL           0x4
10331 #define CHKEOFMARK      0x8
10332
10333 /*
10334  * Push a string back onto the input at this current parsefile level.
10335  * We handle aliases this way.
10336  */
10337 #if !ENABLE_ASH_ALIAS
10338 #define pushstring(s, ap) pushstring(s)
10339 #endif
10340 static void
10341 pushstring(char *s, struct alias *ap)
10342 {
10343         struct strpush *sp;
10344         int len;
10345
10346         len = strlen(s);
10347         INT_OFF;
10348         if (g_parsefile->strpush) {
10349                 sp = ckzalloc(sizeof(*sp));
10350                 sp->prev = g_parsefile->strpush;
10351         } else {
10352                 sp = &(g_parsefile->basestrpush);
10353         }
10354         g_parsefile->strpush = sp;
10355         sp->prev_string = g_parsefile->next_to_pgetc;
10356         sp->prev_left_in_line = g_parsefile->left_in_line;
10357         sp->unget = g_parsefile->unget;
10358         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10359 #if ENABLE_ASH_ALIAS
10360         sp->ap = ap;
10361         if (ap) {
10362                 ap->flag |= ALIASINUSE;
10363                 sp->string = s;
10364         }
10365 #endif
10366         g_parsefile->next_to_pgetc = s;
10367         g_parsefile->left_in_line = len;
10368         g_parsefile->unget = 0;
10369         INT_ON;
10370 }
10371
10372 static void
10373 popstring(void)
10374 {
10375         struct strpush *sp = g_parsefile->strpush;
10376
10377         INT_OFF;
10378 #if ENABLE_ASH_ALIAS
10379         if (sp->ap) {
10380                 if (g_parsefile->next_to_pgetc[-1] == ' '
10381                  || g_parsefile->next_to_pgetc[-1] == '\t'
10382                 ) {
10383                         checkkwd |= CHKALIAS;
10384                 }
10385                 if (sp->string != sp->ap->val) {
10386                         free(sp->string);
10387                 }
10388                 sp->ap->flag &= ~ALIASINUSE;
10389                 if (sp->ap->flag & ALIASDEAD) {
10390                         unalias(sp->ap->name);
10391                 }
10392         }
10393 #endif
10394         g_parsefile->next_to_pgetc = sp->prev_string;
10395         g_parsefile->left_in_line = sp->prev_left_in_line;
10396         g_parsefile->unget = sp->unget;
10397         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10398         g_parsefile->strpush = sp->prev;
10399         if (sp != &(g_parsefile->basestrpush))
10400                 free(sp);
10401         INT_ON;
10402 }
10403
10404 static int
10405 preadfd(void)
10406 {
10407         int nr;
10408         char *buf = g_parsefile->buf;
10409
10410         g_parsefile->next_to_pgetc = buf;
10411 #if ENABLE_FEATURE_EDITING
10412  retry:
10413         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10414                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10415         else {
10416 # if ENABLE_ASH_IDLE_TIMEOUT
10417                 int timeout = -1;
10418                 if (iflag) {
10419                         const char *tmout_var = lookupvar("TMOUT");
10420                         if (tmout_var) {
10421                                 timeout = atoi(tmout_var) * 1000;
10422                                 if (timeout <= 0)
10423                                         timeout = -1;
10424                         }
10425                 }
10426                 line_input_state->timeout = timeout;
10427 # endif
10428 # if ENABLE_FEATURE_TAB_COMPLETION
10429                 line_input_state->path_lookup = pathval();
10430 # endif
10431                 reinit_unicode_for_ash();
10432                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10433                 if (nr == 0) {
10434                         /* ^C pressed, "convert" to SIGINT */
10435                         write(STDOUT_FILENO, "^C", 2);
10436                         if (trap[SIGINT]) {
10437                                 buf[0] = '\n';
10438                                 buf[1] = '\0';
10439                                 raise(SIGINT);
10440                                 return 1;
10441                         }
10442                         exitstatus = 128 + SIGINT;
10443                         bb_putchar('\n');
10444                         goto retry;
10445                 }
10446                 if (nr < 0) {
10447                         if (errno == 0) {
10448                                 /* Ctrl+D pressed */
10449                                 nr = 0;
10450                         }
10451 # if ENABLE_ASH_IDLE_TIMEOUT
10452                         else if (errno == EAGAIN && timeout > 0) {
10453                                 puts("\007timed out waiting for input: auto-logout");
10454                                 exitshell();
10455                         }
10456 # endif
10457                 }
10458         }
10459 #else
10460         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10461 #endif
10462
10463 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10464         if (nr < 0) {
10465                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10466                         int flags = fcntl(0, F_GETFL);
10467                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10468                                 flags &= ~O_NONBLOCK;
10469                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10470                                         out2str("sh: turning off NDELAY mode\n");
10471                                         goto retry;
10472                                 }
10473                         }
10474                 }
10475         }
10476 #endif
10477         return nr;
10478 }
10479
10480 /*
10481  * Refill the input buffer and return the next input character:
10482  *
10483  * 1) If a string was pushed back on the input, pop it;
10484  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10485  *    or we are reading from a string so we can't refill the buffer,
10486  *    return EOF.
10487  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10488  * 4) Process input up to the next newline, deleting nul characters.
10489  */
10490 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10491 #define pgetc_debug(...) ((void)0)
10492 static int pgetc(void);
10493 static int
10494 preadbuffer(void)
10495 {
10496         char *q;
10497         int more;
10498
10499         if (g_parsefile->strpush) {
10500 #if ENABLE_ASH_ALIAS
10501                 if (g_parsefile->left_in_line == -1
10502                  && g_parsefile->strpush->ap
10503                  && g_parsefile->next_to_pgetc[-1] != ' '
10504                  && g_parsefile->next_to_pgetc[-1] != '\t'
10505                 ) {
10506                         pgetc_debug("preadbuffer PEOA");
10507                         return PEOA;
10508                 }
10509 #endif
10510                 popstring();
10511                 return pgetc();
10512         }
10513         /* on both branches above g_parsefile->left_in_line < 0.
10514          * "pgetc" needs refilling.
10515          */
10516
10517         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10518          * pungetc() may increment it a few times.
10519          * Assuming it won't increment it to less than -90.
10520          */
10521         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10522                 pgetc_debug("preadbuffer PEOF1");
10523                 /* even in failure keep left_in_line and next_to_pgetc
10524                  * in lock step, for correct multi-layer pungetc.
10525                  * left_in_line was decremented before preadbuffer(),
10526                  * must inc next_to_pgetc: */
10527                 g_parsefile->next_to_pgetc++;
10528                 return PEOF;
10529         }
10530
10531         more = g_parsefile->left_in_buffer;
10532         if (more <= 0) {
10533                 flush_stdout_stderr();
10534  again:
10535                 more = preadfd();
10536                 if (more <= 0) {
10537                         /* don't try reading again */
10538                         g_parsefile->left_in_line = -99;
10539                         pgetc_debug("preadbuffer PEOF2");
10540                         g_parsefile->next_to_pgetc++;
10541                         return PEOF;
10542                 }
10543         }
10544
10545         /* Find out where's the end of line.
10546          * Set g_parsefile->left_in_line
10547          * and g_parsefile->left_in_buffer acordingly.
10548          * NUL chars are deleted.
10549          */
10550         q = g_parsefile->next_to_pgetc;
10551         for (;;) {
10552                 char c;
10553
10554                 more--;
10555
10556                 c = *q;
10557                 if (c == '\0') {
10558                         memmove(q, q + 1, more);
10559                 } else {
10560                         q++;
10561                         if (c == '\n') {
10562                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10563                                 break;
10564                         }
10565                 }
10566
10567                 if (more <= 0) {
10568                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10569                         if (g_parsefile->left_in_line < 0)
10570                                 goto again;
10571                         break;
10572                 }
10573         }
10574         g_parsefile->left_in_buffer = more;
10575
10576         if (vflag) {
10577                 char save = *q;
10578                 *q = '\0';
10579                 out2str(g_parsefile->next_to_pgetc);
10580                 *q = save;
10581         }
10582
10583         pgetc_debug("preadbuffer at %d:%p'%s'",
10584                         g_parsefile->left_in_line,
10585                         g_parsefile->next_to_pgetc,
10586                         g_parsefile->next_to_pgetc);
10587         return (unsigned char)*g_parsefile->next_to_pgetc++;
10588 }
10589
10590 static void
10591 nlprompt(void)
10592 {
10593         g_parsefile->linno++;
10594         setprompt_if(doprompt, 2);
10595 }
10596 static void
10597 nlnoprompt(void)
10598 {
10599         g_parsefile->linno++;
10600         needprompt = doprompt;
10601 }
10602
10603 static int
10604 pgetc(void)
10605 {
10606         int c;
10607
10608         pgetc_debug("pgetc at %d:%p'%s'",
10609                         g_parsefile->left_in_line,
10610                         g_parsefile->next_to_pgetc,
10611                         g_parsefile->next_to_pgetc);
10612         if (g_parsefile->unget)
10613                 return g_parsefile->lastc[--g_parsefile->unget];
10614
10615         if (--g_parsefile->left_in_line >= 0)
10616                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10617         else
10618                 c = preadbuffer();
10619
10620         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10621         g_parsefile->lastc[0] = c;
10622
10623         return c;
10624 }
10625
10626 #if ENABLE_ASH_ALIAS
10627 static int
10628 pgetc_without_PEOA(void)
10629 {
10630         int c;
10631         do {
10632                 pgetc_debug("pgetc at %d:%p'%s'",
10633                                 g_parsefile->left_in_line,
10634                                 g_parsefile->next_to_pgetc,
10635                                 g_parsefile->next_to_pgetc);
10636                 c = pgetc();
10637         } while (c == PEOA);
10638         return c;
10639 }
10640 #else
10641 # define pgetc_without_PEOA() pgetc()
10642 #endif
10643
10644 /*
10645  * Undo a call to pgetc.  Only two characters may be pushed back.
10646  * PEOF may be pushed back.
10647  */
10648 static void
10649 pungetc(void)
10650 {
10651         g_parsefile->unget++;
10652 }
10653
10654 /* This one eats backslash+newline */
10655 static int
10656 pgetc_eatbnl(void)
10657 {
10658         int c;
10659
10660         while ((c = pgetc()) == '\\') {
10661                 if (pgetc() != '\n') {
10662                         pungetc();
10663                         break;
10664                 }
10665
10666                 nlprompt();
10667         }
10668
10669         return c;
10670 }
10671
10672 /*
10673  * To handle the "." command, a stack of input files is used.  Pushfile
10674  * adds a new entry to the stack and popfile restores the previous level.
10675  */
10676 static void
10677 pushfile(void)
10678 {
10679         struct parsefile *pf;
10680
10681         pf = ckzalloc(sizeof(*pf));
10682         pf->prev = g_parsefile;
10683         pf->pf_fd = -1;
10684         /*pf->strpush = NULL; - ckzalloc did it */
10685         /*pf->basestrpush.prev = NULL;*/
10686         /*pf->unget = 0;*/
10687         g_parsefile = pf;
10688 }
10689
10690 static void
10691 popfile(void)
10692 {
10693         struct parsefile *pf = g_parsefile;
10694
10695         if (pf == &basepf)
10696                 return;
10697
10698         INT_OFF;
10699         if (pf->pf_fd >= 0)
10700                 close(pf->pf_fd);
10701         free(pf->buf);
10702         while (pf->strpush)
10703                 popstring();
10704         g_parsefile = pf->prev;
10705         free(pf);
10706         INT_ON;
10707 }
10708
10709 /*
10710  * Return to top level.
10711  */
10712 static void
10713 popallfiles(void)
10714 {
10715         while (g_parsefile != &basepf)
10716                 popfile();
10717 }
10718
10719 /*
10720  * Close the file(s) that the shell is reading commands from.  Called
10721  * after a fork is done.
10722  */
10723 static void
10724 closescript(void)
10725 {
10726         popallfiles();
10727         if (g_parsefile->pf_fd > 0) {
10728                 close(g_parsefile->pf_fd);
10729                 g_parsefile->pf_fd = 0;
10730         }
10731 }
10732
10733 /*
10734  * Like setinputfile, but takes an open file descriptor.  Call this with
10735  * interrupts off.
10736  */
10737 static void
10738 setinputfd(int fd, int push)
10739 {
10740         if (push) {
10741                 pushfile();
10742                 g_parsefile->buf = NULL;
10743         }
10744         g_parsefile->pf_fd = fd;
10745         if (g_parsefile->buf == NULL)
10746                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10747         g_parsefile->left_in_buffer = 0;
10748         g_parsefile->left_in_line = 0;
10749         g_parsefile->linno = 1;
10750 }
10751
10752 /*
10753  * Set the input to take input from a file.  If push is set, push the
10754  * old input onto the stack first.
10755  */
10756 static int
10757 setinputfile(const char *fname, int flags)
10758 {
10759         int fd;
10760
10761         INT_OFF;
10762         fd = open(fname, O_RDONLY | O_CLOEXEC);
10763         if (fd < 0) {
10764                 if (flags & INPUT_NOFILE_OK)
10765                         goto out;
10766                 exitstatus = 127;
10767                 ash_msg_and_raise_perror("can't open '%s'", fname);
10768         }
10769         if (fd < 10)
10770                 fd = savefd(fd);
10771         else if (O_CLOEXEC == 0) /* old libc */
10772                 close_on_exec_on(fd);
10773
10774         setinputfd(fd, flags & INPUT_PUSH_FILE);
10775  out:
10776         INT_ON;
10777         return fd;
10778 }
10779
10780 /*
10781  * Like setinputfile, but takes input from a string.
10782  */
10783 static void
10784 setinputstring(char *string)
10785 {
10786         INT_OFF;
10787         pushfile();
10788         g_parsefile->next_to_pgetc = string;
10789         g_parsefile->left_in_line = strlen(string);
10790         g_parsefile->buf = NULL;
10791         g_parsefile->linno = 1;
10792         INT_ON;
10793 }
10794
10795
10796 /*
10797  * Routines to check for mail.
10798  */
10799
10800 #if ENABLE_ASH_MAIL
10801
10802 /* Hash of mtimes of mailboxes */
10803 static unsigned mailtime_hash;
10804 /* Set if MAIL or MAILPATH is changed. */
10805 static smallint mail_var_path_changed;
10806
10807 /*
10808  * Print appropriate message(s) if mail has arrived.
10809  * If mail_var_path_changed is set,
10810  * then the value of MAIL has mail_var_path_changed,
10811  * so we just update the values.
10812  */
10813 static void
10814 chkmail(void)
10815 {
10816         const char *mpath;
10817         char *p;
10818         char *q;
10819         unsigned new_hash;
10820         struct stackmark smark;
10821         struct stat statb;
10822
10823         setstackmark(&smark);
10824         mpath = mpathset() ? mpathval() : mailval();
10825         new_hash = 0;
10826         for (;;) {
10827                 p = path_advance(&mpath, nullstr);
10828                 if (p == NULL)
10829                         break;
10830                 if (*p == '\0')
10831                         continue;
10832                 for (q = p; *q; q++)
10833                         continue;
10834 #if DEBUG
10835                 if (q[-1] != '/')
10836                         abort();
10837 #endif
10838                 q[-1] = '\0';                   /* delete trailing '/' */
10839                 if (stat(p, &statb) < 0) {
10840                         continue;
10841                 }
10842                 /* Very simplistic "hash": just a sum of all mtimes */
10843                 new_hash += (unsigned)statb.st_mtime;
10844         }
10845         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10846                 if (mailtime_hash != 0)
10847                         out2str("you have mail\n");
10848                 mailtime_hash = new_hash;
10849         }
10850         mail_var_path_changed = 0;
10851         popstackmark(&smark);
10852 }
10853
10854 static void FAST_FUNC
10855 changemail(const char *val UNUSED_PARAM)
10856 {
10857         mail_var_path_changed = 1;
10858 }
10859
10860 #endif /* ASH_MAIL */
10861
10862
10863 /* ============ ??? */
10864
10865 /*
10866  * Set the shell parameters.
10867  */
10868 static void
10869 setparam(char **argv)
10870 {
10871         char **newparam;
10872         char **ap;
10873         int nparam;
10874
10875         for (nparam = 0; argv[nparam]; nparam++)
10876                 continue;
10877         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10878         while (*argv) {
10879                 *ap++ = ckstrdup(*argv++);
10880         }
10881         *ap = NULL;
10882         freeparam(&shellparam);
10883         shellparam.malloced = 1;
10884         shellparam.nparam = nparam;
10885         shellparam.p = newparam;
10886 #if ENABLE_ASH_GETOPTS
10887         shellparam.optind = 1;
10888         shellparam.optoff = -1;
10889 #endif
10890 }
10891
10892 /*
10893  * Process shell options.  The global variable argptr contains a pointer
10894  * to the argument list; we advance it past the options.
10895  *
10896  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10897  * For a non-interactive shell, an error condition encountered
10898  * by a special built-in ... shall cause the shell to write a diagnostic message
10899  * to standard error and exit as shown in the following table:
10900  * Error                                           Special Built-In
10901  * ...
10902  * Utility syntax error (option or operand error)  Shall exit
10903  * ...
10904  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10905  * we see that bash does not do that (set "finishes" with error code 1 instead,
10906  * and shell continues), and people rely on this behavior!
10907  * Testcase:
10908  * set -o barfoo 2>/dev/null
10909  * echo $?
10910  *
10911  * Oh well. Let's mimic that.
10912  */
10913 static int
10914 plus_minus_o(char *name, int val)
10915 {
10916         int i;
10917
10918         if (name) {
10919                 for (i = 0; i < NOPTS; i++) {
10920                         if (strcmp(name, optnames(i)) == 0) {
10921                                 optlist[i] = val;
10922                                 return 0;
10923                         }
10924                 }
10925                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10926                 return 1;
10927         }
10928         for (i = 0; i < NOPTS; i++) {
10929                 if (val) {
10930                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10931                 } else {
10932                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10933                 }
10934         }
10935         return 0;
10936 }
10937 static void
10938 setoption(int flag, int val)
10939 {
10940         int i;
10941
10942         for (i = 0; i < NOPTS; i++) {
10943                 if (optletters(i) == flag) {
10944                         optlist[i] = val;
10945                         return;
10946                 }
10947         }
10948         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10949         /* NOTREACHED */
10950 }
10951 static int
10952 options(int cmdline, int *login_sh)
10953 {
10954         char *p;
10955         int val;
10956         int c;
10957
10958         if (cmdline)
10959                 minusc = NULL;
10960         while ((p = *argptr) != NULL) {
10961                 c = *p++;
10962                 if (c != '-' && c != '+')
10963                         break;
10964                 argptr++;
10965                 val = 0; /* val = 0 if c == '+' */
10966                 if (c == '-') {
10967                         val = 1;
10968                         if (p[0] == '\0' || LONE_DASH(p)) {
10969                                 if (!cmdline) {
10970                                         /* "-" means turn off -x and -v */
10971                                         if (p[0] == '\0')
10972                                                 xflag = vflag = 0;
10973                                         /* "--" means reset params */
10974                                         else if (*argptr == NULL)
10975                                                 setparam(argptr);
10976                                 }
10977                                 break;    /* "-" or "--" terminates options */
10978                         }
10979                 }
10980                 /* first char was + or - */
10981                 while ((c = *p++) != '\0') {
10982                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10983                         if (c == 'c' && cmdline) {
10984                                 minusc = p;     /* command is after shell args */
10985                         } else if (c == 'o') {
10986                                 if (plus_minus_o(*argptr, val)) {
10987                                         /* it already printed err message */
10988                                         return 1; /* error */
10989                                 }
10990                                 if (*argptr)
10991                                         argptr++;
10992                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10993                                 if (login_sh)
10994                                         *login_sh = 1;
10995                         /* bash does not accept +-login, we also won't */
10996                         } else if (cmdline && val && (c == '-')) { /* long options */
10997                                 if (strcmp(p, "login") == 0) {
10998                                         if (login_sh)
10999                                                 *login_sh = 1;
11000                                 }
11001                                 break;
11002                         } else {
11003                                 setoption(c, val);
11004                         }
11005                 }
11006         }
11007         return 0;
11008 }
11009
11010 /*
11011  * The shift builtin command.
11012  */
11013 static int FAST_FUNC
11014 shiftcmd(int argc UNUSED_PARAM, char **argv)
11015 {
11016         int n;
11017         char **ap1, **ap2;
11018
11019         n = 1;
11020         if (argv[1])
11021                 n = number(argv[1]);
11022         if (n > shellparam.nparam)
11023                 return 1;
11024         INT_OFF;
11025         shellparam.nparam -= n;
11026         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11027                 if (shellparam.malloced)
11028                         free(*ap1);
11029         }
11030         ap2 = shellparam.p;
11031         while ((*ap2++ = *ap1++) != NULL)
11032                 continue;
11033 #if ENABLE_ASH_GETOPTS
11034         shellparam.optind = 1;
11035         shellparam.optoff = -1;
11036 #endif
11037         INT_ON;
11038         return 0;
11039 }
11040
11041 /*
11042  * POSIX requires that 'set' (but not export or readonly) output the
11043  * variables in lexicographic order - by the locale's collating order (sigh).
11044  * Maybe we could keep them in an ordered balanced binary tree
11045  * instead of hashed lists.
11046  * For now just roll 'em through qsort for printing...
11047  */
11048 static int
11049 showvars(const char *sep_prefix, int on, int off)
11050 {
11051         const char *sep;
11052         char **ep, **epend;
11053
11054         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11055         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11056
11057         sep = *sep_prefix ? " " : sep_prefix;
11058
11059         for (; ep < epend; ep++) {
11060                 const char *p;
11061                 const char *q;
11062
11063                 p = endofname(*ep);
11064 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11065  * makes "export -p" to have output not suitable for "eval":
11066  * import os
11067  * os.environ["test-test"]="test"
11068  * if os.fork() == 0:
11069  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11070  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11071  */
11072                 q = nullstr;
11073                 if (*p == '=')
11074                         q = single_quote(++p);
11075                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11076         }
11077         return 0;
11078 }
11079
11080 /*
11081  * The set command builtin.
11082  */
11083 static int FAST_FUNC
11084 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11085 {
11086         int retval;
11087
11088         if (!argv[1])
11089                 return showvars(nullstr, 0, VUNSET);
11090
11091         INT_OFF;
11092         retval = options(/*cmdline:*/ 0, NULL);
11093         if (retval == 0) { /* if no parse error... */
11094                 optschanged();
11095                 if (*argptr != NULL) {
11096                         setparam(argptr);
11097                 }
11098         }
11099         INT_ON;
11100         return retval;
11101 }
11102
11103 #if ENABLE_ASH_RANDOM_SUPPORT
11104 static void FAST_FUNC
11105 change_random(const char *value)
11106 {
11107         uint32_t t;
11108
11109         if (value == NULL) {
11110                 /* "get", generate */
11111                 t = next_random(&random_gen);
11112                 /* set without recursion */
11113                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11114                 vrandom.flags &= ~VNOFUNC;
11115         } else {
11116                 /* set/reset */
11117                 t = strtoul(value, NULL, 10);
11118                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11119         }
11120 }
11121 #endif
11122
11123 #if ENABLE_ASH_GETOPTS
11124 static int
11125 getopts(char *optstr, char *optvar, char **optfirst)
11126 {
11127         char *p, *q;
11128         char c = '?';
11129         int done = 0;
11130         char sbuf[2];
11131         char **optnext;
11132         int ind = shellparam.optind;
11133         int off = shellparam.optoff;
11134
11135         sbuf[1] = '\0';
11136
11137         shellparam.optind = -1;
11138         optnext = optfirst + ind - 1;
11139
11140         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11141                 p = NULL;
11142         else
11143                 p = optnext[-1] + off;
11144         if (p == NULL || *p == '\0') {
11145                 /* Current word is done, advance */
11146                 p = *optnext;
11147                 if (p == NULL || *p != '-' || *++p == '\0') {
11148  atend:
11149                         unsetvar("OPTARG");
11150                         p = NULL;
11151                         done = 1;
11152                         goto out;
11153                 }
11154                 optnext++;
11155                 if (LONE_DASH(p))        /* check for "--" */
11156                         goto atend;
11157         }
11158
11159         c = *p++;
11160         for (q = optstr; *q != c;) {
11161                 if (*q == '\0') {
11162                         /* OPTERR is a bashism */
11163                         const char *cp = lookupvar("OPTERR");
11164                         if ((cp && LONE_CHAR(cp, '0'))
11165                          || (optstr[0] == ':')
11166                         ) {
11167                                 sbuf[0] = c;
11168                                 /*sbuf[1] = '\0'; - already is */
11169                                 setvar0("OPTARG", sbuf);
11170                         } else {
11171                                 fprintf(stderr, "Illegal option -%c\n", c);
11172                                 unsetvar("OPTARG");
11173                         }
11174                         c = '?';
11175                         goto out;
11176                 }
11177                 if (*++q == ':')
11178                         q++;
11179         }
11180
11181         if (*++q == ':') {
11182                 if (*p == '\0' && (p = *optnext) == NULL) {
11183                         /* OPTERR is a bashism */
11184                         const char *cp = lookupvar("OPTERR");
11185                         if ((cp && LONE_CHAR(cp, '0'))
11186                          || (optstr[0] == ':')
11187                         ) {
11188                                 sbuf[0] = c;
11189                                 /*sbuf[1] = '\0'; - already is */
11190                                 setvar0("OPTARG", sbuf);
11191                                 c = ':';
11192                         } else {
11193                                 fprintf(stderr, "No arg for -%c option\n", c);
11194                                 unsetvar("OPTARG");
11195                                 c = '?';
11196                         }
11197                         goto out;
11198                 }
11199
11200                 if (p == *optnext)
11201                         optnext++;
11202                 setvar0("OPTARG", p);
11203                 p = NULL;
11204         } else
11205                 setvar0("OPTARG", nullstr);
11206  out:
11207         ind = optnext - optfirst + 1;
11208         setvar("OPTIND", itoa(ind), VNOFUNC);
11209         sbuf[0] = c;
11210         /*sbuf[1] = '\0'; - already is */
11211         setvar0(optvar, sbuf);
11212
11213         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11214         shellparam.optind = ind;
11215
11216         return done;
11217 }
11218
11219 /*
11220  * The getopts builtin.  Shellparam.optnext points to the next argument
11221  * to be processed.  Shellparam.optptr points to the next character to
11222  * be processed in the current argument.  If shellparam.optnext is NULL,
11223  * then it's the first time getopts has been called.
11224  */
11225 static int FAST_FUNC
11226 getoptscmd(int argc, char **argv)
11227 {
11228         char **optbase;
11229
11230         if (argc < 3)
11231                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11232         if (argc == 3) {
11233                 optbase = shellparam.p;
11234                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11235                         shellparam.optind = 1;
11236                         shellparam.optoff = -1;
11237                 }
11238         } else {
11239                 optbase = &argv[3];
11240                 if ((unsigned)shellparam.optind > argc - 2) {
11241                         shellparam.optind = 1;
11242                         shellparam.optoff = -1;
11243                 }
11244         }
11245
11246         return getopts(argv[1], argv[2], optbase);
11247 }
11248 #endif /* ASH_GETOPTS */
11249
11250
11251 /* ============ Shell parser */
11252
11253 struct heredoc {
11254         struct heredoc *next;   /* next here document in list */
11255         union node *here;       /* redirection node */
11256         char *eofmark;          /* string indicating end of input */
11257         smallint striptabs;     /* if set, strip leading tabs */
11258 };
11259
11260 static smallint tokpushback;           /* last token pushed back */
11261 static smallint quoteflag;             /* set if (part of) last token was quoted */
11262 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11263 static struct heredoc *heredoclist;    /* list of here documents to read */
11264 static char *wordtext;                 /* text of last word returned by readtoken */
11265 static struct nodelist *backquotelist;
11266 static union node *redirnode;
11267 static struct heredoc *heredoc;
11268
11269 static const char *
11270 tokname(char *buf, int tok)
11271 {
11272         if (tok < TSEMI)
11273                 return tokname_array[tok];
11274         sprintf(buf, "\"%s\"", tokname_array[tok]);
11275         return buf;
11276 }
11277
11278 /* raise_error_unexpected_syntax:
11279  * Called when an unexpected token is read during the parse.  The argument
11280  * is the token that is expected, or -1 if more than one type of token can
11281  * occur at this point.
11282  */
11283 static void raise_error_unexpected_syntax(int) NORETURN;
11284 static void
11285 raise_error_unexpected_syntax(int token)
11286 {
11287         char msg[64];
11288         char buf[16];
11289         int l;
11290
11291         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11292         if (token >= 0)
11293                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11294         raise_error_syntax(msg);
11295         /* NOTREACHED */
11296 }
11297
11298 /* parsing is heavily cross-recursive, need these forward decls */
11299 static union node *andor(void);
11300 static union node *pipeline(void);
11301 static union node *parse_command(void);
11302 static void parseheredoc(void);
11303 static int peektoken(void);
11304 static int readtoken(void);
11305
11306 static union node *
11307 list(int nlflag)
11308 {
11309         union node *n1, *n2, *n3;
11310         int tok;
11311
11312         n1 = NULL;
11313         for (;;) {
11314                 switch (peektoken()) {
11315                 case TNL:
11316                         if (!(nlflag & 1))
11317                                 break;
11318                         parseheredoc();
11319                         return n1;
11320
11321                 case TEOF:
11322                         if (!n1 && (nlflag & 1))
11323                                 n1 = NODE_EOF;
11324                         parseheredoc();
11325                         return n1;
11326                 }
11327
11328                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11329                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11330                         return n1;
11331                 nlflag |= 2;
11332
11333                 n2 = andor();
11334                 tok = readtoken();
11335                 if (tok == TBACKGND) {
11336                         if (n2->type == NPIPE) {
11337                                 n2->npipe.pipe_backgnd = 1;
11338                         } else {
11339                                 if (n2->type != NREDIR) {
11340                                         n3 = stzalloc(sizeof(struct nredir));
11341                                         n3->nredir.n = n2;
11342                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11343                                         n2 = n3;
11344                                 }
11345                                 n2->type = NBACKGND;
11346                         }
11347                 }
11348                 if (n1 == NULL) {
11349                         n1 = n2;
11350                 } else {
11351                         n3 = stzalloc(sizeof(struct nbinary));
11352                         n3->type = NSEMI;
11353                         n3->nbinary.ch1 = n1;
11354                         n3->nbinary.ch2 = n2;
11355                         n1 = n3;
11356                 }
11357                 switch (tok) {
11358                 case TNL:
11359                 case TEOF:
11360                         tokpushback = 1;
11361                         /* fall through */
11362                 case TBACKGND:
11363                 case TSEMI:
11364                         break;
11365                 default:
11366                         if ((nlflag & 1))
11367                                 raise_error_unexpected_syntax(-1);
11368                         tokpushback = 1;
11369                         return n1;
11370                 }
11371         }
11372 }
11373
11374 static union node *
11375 andor(void)
11376 {
11377         union node *n1, *n2, *n3;
11378         int t;
11379
11380         n1 = pipeline();
11381         for (;;) {
11382                 t = readtoken();
11383                 if (t == TAND) {
11384                         t = NAND;
11385                 } else if (t == TOR) {
11386                         t = NOR;
11387                 } else {
11388                         tokpushback = 1;
11389                         return n1;
11390                 }
11391                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11392                 n2 = pipeline();
11393                 n3 = stzalloc(sizeof(struct nbinary));
11394                 n3->type = t;
11395                 n3->nbinary.ch1 = n1;
11396                 n3->nbinary.ch2 = n2;
11397                 n1 = n3;
11398         }
11399 }
11400
11401 static union node *
11402 pipeline(void)
11403 {
11404         union node *n1, *n2, *pipenode;
11405         struct nodelist *lp, *prev;
11406         int negate;
11407
11408         negate = 0;
11409         TRACE(("pipeline: entered\n"));
11410         if (readtoken() == TNOT) {
11411                 negate = !negate;
11412                 checkkwd = CHKKWD | CHKALIAS;
11413         } else
11414                 tokpushback = 1;
11415         n1 = parse_command();
11416         if (readtoken() == TPIPE) {
11417                 pipenode = stzalloc(sizeof(struct npipe));
11418                 pipenode->type = NPIPE;
11419                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11420                 lp = stzalloc(sizeof(struct nodelist));
11421                 pipenode->npipe.cmdlist = lp;
11422                 lp->n = n1;
11423                 do {
11424                         prev = lp;
11425                         lp = stzalloc(sizeof(struct nodelist));
11426                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11427                         lp->n = parse_command();
11428                         prev->next = lp;
11429                 } while (readtoken() == TPIPE);
11430                 lp->next = NULL;
11431                 n1 = pipenode;
11432         }
11433         tokpushback = 1;
11434         if (negate) {
11435                 n2 = stzalloc(sizeof(struct nnot));
11436                 n2->type = NNOT;
11437                 n2->nnot.com = n1;
11438                 return n2;
11439         }
11440         return n1;
11441 }
11442
11443 static union node *
11444 makename(void)
11445 {
11446         union node *n;
11447
11448         n = stzalloc(sizeof(struct narg));
11449         n->type = NARG;
11450         /*n->narg.next = NULL; - stzalloc did it */
11451         n->narg.text = wordtext;
11452         n->narg.backquote = backquotelist;
11453         return n;
11454 }
11455
11456 static void
11457 fixredir(union node *n, const char *text, int err)
11458 {
11459         int fd;
11460
11461         TRACE(("Fix redir %s %d\n", text, err));
11462         if (!err)
11463                 n->ndup.vname = NULL;
11464
11465         fd = bb_strtou(text, NULL, 10);
11466         if (!errno && fd >= 0)
11467                 n->ndup.dupfd = fd;
11468         else if (LONE_DASH(text))
11469                 n->ndup.dupfd = -1;
11470         else {
11471                 if (err)
11472                         raise_error_syntax("bad fd number");
11473                 n->ndup.vname = makename();
11474         }
11475 }
11476
11477 static void
11478 parsefname(void)
11479 {
11480         union node *n = redirnode;
11481
11482         if (n->type == NHERE)
11483                 checkkwd = CHKEOFMARK;
11484         if (readtoken() != TWORD)
11485                 raise_error_unexpected_syntax(-1);
11486         if (n->type == NHERE) {
11487                 struct heredoc *here = heredoc;
11488                 struct heredoc *p;
11489
11490                 if (quoteflag == 0)
11491                         n->type = NXHERE;
11492                 TRACE(("Here document %d\n", n->type));
11493                 rmescapes(wordtext, 0, NULL);
11494                 here->eofmark = wordtext;
11495                 here->next = NULL;
11496                 if (heredoclist == NULL)
11497                         heredoclist = here;
11498                 else {
11499                         for (p = heredoclist; p->next; p = p->next)
11500                                 continue;
11501                         p->next = here;
11502                 }
11503         } else if (n->type == NTOFD || n->type == NFROMFD) {
11504                 fixredir(n, wordtext, 0);
11505         } else {
11506                 n->nfile.fname = makename();
11507         }
11508 }
11509
11510 static union node *
11511 simplecmd(void)
11512 {
11513         union node *args, **app;
11514         union node *n = NULL;
11515         union node *vars, **vpp;
11516         union node **rpp, *redir;
11517         int savecheckkwd;
11518         int savelinno;
11519 #if BASH_TEST2
11520         smallint double_brackets_flag = 0;
11521 #endif
11522         IF_BASH_FUNCTION(smallint function_flag = 0;)
11523
11524         args = NULL;
11525         app = &args;
11526         vars = NULL;
11527         vpp = &vars;
11528         redir = NULL;
11529         rpp = &redir;
11530
11531         savecheckkwd = CHKALIAS;
11532         savelinno = g_parsefile->linno;
11533         for (;;) {
11534                 int t;
11535                 checkkwd = savecheckkwd;
11536                 t = readtoken();
11537                 switch (t) {
11538 #if BASH_FUNCTION
11539                 case TFUNCTION:
11540                         if (peektoken() != TWORD)
11541                                 raise_error_unexpected_syntax(TWORD);
11542                         function_flag = 1;
11543                         break;
11544 #endif
11545 #if BASH_TEST2
11546                 case TAND: /* "&&" */
11547                 case TOR: /* "||" */
11548                         if (!double_brackets_flag) {
11549                                 tokpushback = 1;
11550                                 goto out;
11551                         }
11552                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11553 #endif
11554                 case TWORD:
11555                         n = stzalloc(sizeof(struct narg));
11556                         n->type = NARG;
11557                         /*n->narg.next = NULL; - stzalloc did it */
11558                         n->narg.text = wordtext;
11559 #if BASH_TEST2
11560                         if (strcmp("[[", wordtext) == 0)
11561                                 double_brackets_flag = 1;
11562                         else if (strcmp("]]", wordtext) == 0)
11563                                 double_brackets_flag = 0;
11564 #endif
11565                         n->narg.backquote = backquotelist;
11566                         if (savecheckkwd && isassignment(wordtext)) {
11567                                 *vpp = n;
11568                                 vpp = &n->narg.next;
11569                         } else {
11570                                 *app = n;
11571                                 app = &n->narg.next;
11572                                 savecheckkwd = 0;
11573                         }
11574 #if BASH_FUNCTION
11575                         if (function_flag) {
11576                                 checkkwd = CHKNL | CHKKWD;
11577                                 switch (peektoken()) {
11578                                 case TBEGIN:
11579                                 case TIF:
11580                                 case TCASE:
11581                                 case TUNTIL:
11582                                 case TWHILE:
11583                                 case TFOR:
11584                                         goto do_func;
11585                                 case TLP:
11586                                         function_flag = 0;
11587                                         break;
11588                                 case TWORD:
11589                                         if (strcmp("[[", wordtext) == 0)
11590                                                 goto do_func;
11591                                         /* fall through */
11592                                 default:
11593                                         raise_error_unexpected_syntax(-1);
11594                                 }
11595                         }
11596 #endif
11597                         break;
11598                 case TREDIR:
11599                         *rpp = n = redirnode;
11600                         rpp = &n->nfile.next;
11601                         parsefname();   /* read name of redirection file */
11602                         break;
11603                 case TLP:
11604  IF_BASH_FUNCTION(do_func:)
11605                         if (args && app == &args->narg.next
11606                          && !vars && !redir
11607                         ) {
11608                                 struct builtincmd *bcmd;
11609                                 const char *name;
11610
11611                                 /* We have a function */
11612                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11613                                         raise_error_unexpected_syntax(TRP);
11614                                 name = n->narg.text;
11615                                 if (!goodname(name)
11616                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11617                                 ) {
11618                                         raise_error_syntax("bad function name");
11619                                 }
11620                                 n->type = NDEFUN;
11621                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11622                                 n->ndefun.text = n->narg.text;
11623                                 n->ndefun.linno = g_parsefile->linno;
11624                                 n->ndefun.body = parse_command();
11625                                 return n;
11626                         }
11627                         IF_BASH_FUNCTION(function_flag = 0;)
11628                         /* fall through */
11629                 default:
11630                         tokpushback = 1;
11631                         goto out;
11632                 }
11633         }
11634  out:
11635         *app = NULL;
11636         *vpp = NULL;
11637         *rpp = NULL;
11638         n = stzalloc(sizeof(struct ncmd));
11639         n->type = NCMD;
11640         n->ncmd.linno = savelinno;
11641         n->ncmd.args = args;
11642         n->ncmd.assign = vars;
11643         n->ncmd.redirect = redir;
11644         return n;
11645 }
11646
11647 static union node *
11648 parse_command(void)
11649 {
11650         union node *n1, *n2;
11651         union node *ap, **app;
11652         union node *cp, **cpp;
11653         union node *redir, **rpp;
11654         union node **rpp2;
11655         int t;
11656         int savelinno;
11657
11658         redir = NULL;
11659         rpp2 = &redir;
11660
11661         savelinno = g_parsefile->linno;
11662
11663         switch (readtoken()) {
11664         default:
11665                 raise_error_unexpected_syntax(-1);
11666                 /* NOTREACHED */
11667         case TIF:
11668                 n1 = stzalloc(sizeof(struct nif));
11669                 n1->type = NIF;
11670                 n1->nif.test = list(0);
11671                 if (readtoken() != TTHEN)
11672                         raise_error_unexpected_syntax(TTHEN);
11673                 n1->nif.ifpart = list(0);
11674                 n2 = n1;
11675                 while (readtoken() == TELIF) {
11676                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11677                         n2 = n2->nif.elsepart;
11678                         n2->type = NIF;
11679                         n2->nif.test = list(0);
11680                         if (readtoken() != TTHEN)
11681                                 raise_error_unexpected_syntax(TTHEN);
11682                         n2->nif.ifpart = list(0);
11683                 }
11684                 if (lasttoken == TELSE)
11685                         n2->nif.elsepart = list(0);
11686                 else {
11687                         n2->nif.elsepart = NULL;
11688                         tokpushback = 1;
11689                 }
11690                 t = TFI;
11691                 break;
11692         case TWHILE:
11693         case TUNTIL: {
11694                 int got;
11695                 n1 = stzalloc(sizeof(struct nbinary));
11696                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11697                 n1->nbinary.ch1 = list(0);
11698                 got = readtoken();
11699                 if (got != TDO) {
11700                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11701                                         got == TWORD ? wordtext : ""));
11702                         raise_error_unexpected_syntax(TDO);
11703                 }
11704                 n1->nbinary.ch2 = list(0);
11705                 t = TDONE;
11706                 break;
11707         }
11708         case TFOR:
11709                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11710                         raise_error_syntax("bad for loop variable");
11711                 n1 = stzalloc(sizeof(struct nfor));
11712                 n1->type = NFOR;
11713                 n1->nfor.linno = savelinno;
11714                 n1->nfor.var = wordtext;
11715                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11716                 if (readtoken() == TIN) {
11717                         app = &ap;
11718                         while (readtoken() == TWORD) {
11719                                 n2 = stzalloc(sizeof(struct narg));
11720                                 n2->type = NARG;
11721                                 /*n2->narg.next = NULL; - stzalloc did it */
11722                                 n2->narg.text = wordtext;
11723                                 n2->narg.backquote = backquotelist;
11724                                 *app = n2;
11725                                 app = &n2->narg.next;
11726                         }
11727                         *app = NULL;
11728                         n1->nfor.args = ap;
11729                         if (lasttoken != TNL && lasttoken != TSEMI)
11730                                 raise_error_unexpected_syntax(-1);
11731                 } else {
11732                         n2 = stzalloc(sizeof(struct narg));
11733                         n2->type = NARG;
11734                         /*n2->narg.next = NULL; - stzalloc did it */
11735                         n2->narg.text = (char *)dolatstr;
11736                         /*n2->narg.backquote = NULL;*/
11737                         n1->nfor.args = n2;
11738                         /*
11739                          * Newline or semicolon here is optional (but note
11740                          * that the original Bourne shell only allowed NL).
11741                          */
11742                         if (lasttoken != TSEMI)
11743                                 tokpushback = 1;
11744                 }
11745                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11746                 if (readtoken() != TDO)
11747                         raise_error_unexpected_syntax(TDO);
11748                 n1->nfor.body = list(0);
11749                 t = TDONE;
11750                 break;
11751         case TCASE:
11752                 n1 = stzalloc(sizeof(struct ncase));
11753                 n1->type = NCASE;
11754                 n1->ncase.linno = savelinno;
11755                 if (readtoken() != TWORD)
11756                         raise_error_unexpected_syntax(TWORD);
11757                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11758                 n2->type = NARG;
11759                 /*n2->narg.next = NULL; - stzalloc did it */
11760                 n2->narg.text = wordtext;
11761                 n2->narg.backquote = backquotelist;
11762                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11763                 if (readtoken() != TIN)
11764                         raise_error_unexpected_syntax(TIN);
11765                 cpp = &n1->ncase.cases;
11766  next_case:
11767                 checkkwd = CHKNL | CHKKWD;
11768                 t = readtoken();
11769                 while (t != TESAC) {
11770                         if (lasttoken == TLP)
11771                                 readtoken();
11772                         *cpp = cp = stzalloc(sizeof(struct nclist));
11773                         cp->type = NCLIST;
11774                         app = &cp->nclist.pattern;
11775                         for (;;) {
11776                                 *app = ap = stzalloc(sizeof(struct narg));
11777                                 ap->type = NARG;
11778                                 /*ap->narg.next = NULL; - stzalloc did it */
11779                                 ap->narg.text = wordtext;
11780                                 ap->narg.backquote = backquotelist;
11781                                 if (readtoken() != TPIPE)
11782                                         break;
11783                                 app = &ap->narg.next;
11784                                 readtoken();
11785                         }
11786                         //ap->narg.next = NULL;
11787                         if (lasttoken != TRP)
11788                                 raise_error_unexpected_syntax(TRP);
11789                         cp->nclist.body = list(2);
11790
11791                         cpp = &cp->nclist.next;
11792
11793                         checkkwd = CHKNL | CHKKWD;
11794                         t = readtoken();
11795                         if (t != TESAC) {
11796                                 if (t != TENDCASE)
11797                                         raise_error_unexpected_syntax(TENDCASE);
11798                                 goto next_case;
11799                         }
11800                 }
11801                 *cpp = NULL;
11802                 goto redir;
11803         case TLP:
11804                 n1 = stzalloc(sizeof(struct nredir));
11805                 n1->type = NSUBSHELL;
11806                 n1->nredir.linno = savelinno;
11807                 n1->nredir.n = list(0);
11808                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11809                 t = TRP;
11810                 break;
11811         case TBEGIN:
11812                 n1 = list(0);
11813                 t = TEND;
11814                 break;
11815         IF_BASH_FUNCTION(case TFUNCTION:)
11816         case TWORD:
11817         case TREDIR:
11818                 tokpushback = 1;
11819                 return simplecmd();
11820         }
11821
11822         if (readtoken() != t)
11823                 raise_error_unexpected_syntax(t);
11824
11825  redir:
11826         /* Now check for redirection which may follow command */
11827         checkkwd = CHKKWD | CHKALIAS;
11828         rpp = rpp2;
11829         while (readtoken() == TREDIR) {
11830                 *rpp = n2 = redirnode;
11831                 rpp = &n2->nfile.next;
11832                 parsefname();
11833         }
11834         tokpushback = 1;
11835         *rpp = NULL;
11836         if (redir) {
11837                 if (n1->type != NSUBSHELL) {
11838                         n2 = stzalloc(sizeof(struct nredir));
11839                         n2->type = NREDIR;
11840                         n2->nredir.linno = savelinno;
11841                         n2->nredir.n = n1;
11842                         n1 = n2;
11843                 }
11844                 n1->nredir.redirect = redir;
11845         }
11846         return n1;
11847 }
11848
11849 #if BASH_DOLLAR_SQUOTE
11850 static int
11851 decode_dollar_squote(void)
11852 {
11853         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11854         int c, cnt;
11855         char *p;
11856         char buf[4];
11857
11858         c = pgetc();
11859         p = strchr(C_escapes, c);
11860         if (p) {
11861                 buf[0] = c;
11862                 p = buf;
11863                 cnt = 3;
11864                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11865                         do {
11866                                 c = pgetc();
11867                                 *++p = c;
11868                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11869                         pungetc();
11870                 } else if (c == 'x') { /* \xHH */
11871                         do {
11872                                 c = pgetc();
11873                                 *++p = c;
11874                         } while (isxdigit(c) && --cnt);
11875                         pungetc();
11876                         if (cnt == 3) { /* \x but next char is "bad" */
11877                                 c = 'x';
11878                                 goto unrecognized;
11879                         }
11880                 } else { /* simple seq like \\ or \t */
11881                         p++;
11882                 }
11883                 *p = '\0';
11884                 p = buf;
11885                 c = bb_process_escape_sequence((void*)&p);
11886         } else { /* unrecognized "\z": print both chars unless ' or " */
11887                 if (c != '\'' && c != '"') {
11888  unrecognized:
11889                         c |= 0x100; /* "please encode \, then me" */
11890                 }
11891         }
11892         return c;
11893 }
11894 #endif
11895
11896 /* Used by expandstr to get here-doc like behaviour. */
11897 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11898
11899 static ALWAYS_INLINE int
11900 realeofmark(const char *eofmark)
11901 {
11902         return eofmark && eofmark != FAKEEOFMARK;
11903 }
11904
11905 /*
11906  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11907  * is not NULL, read a here document.  In the latter case, eofmark is the
11908  * word which marks the end of the document and striptabs is true if
11909  * leading tabs should be stripped from the document.  The argument c
11910  * is the first character of the input token or document.
11911  *
11912  * Because C does not have internal subroutines, I have simulated them
11913  * using goto's to implement the subroutine linkage.  The following macros
11914  * will run code that appears at the end of readtoken1.
11915  */
11916 #define CHECKEND()      {goto checkend; checkend_return:;}
11917 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11918 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11919 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11920 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11921 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11922 static int
11923 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11924 {
11925         /* NB: syntax parameter fits into smallint */
11926         /* c parameter is an unsigned char or PEOF or PEOA */
11927         char *out;
11928         size_t len;
11929         struct nodelist *bqlist;
11930         smallint quotef;
11931         smallint dblquote;
11932         smallint oldstyle;
11933         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11934         smallint pssyntax;   /* we are expanding a prompt string */
11935         int varnest;         /* levels of variables expansion */
11936         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11937         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11938         int dqvarnest;       /* levels of variables expansion within double quotes */
11939         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11940
11941         bqlist = NULL;
11942         quotef = 0;
11943         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11944 #if ENABLE_ASH_EXPAND_PRMT
11945         pssyntax = (syntax == PSSYNTAX);
11946         if (pssyntax)
11947                 syntax = DQSYNTAX;
11948 #else
11949         pssyntax = 0; /* constant */
11950 #endif
11951         dblquote = (syntax == DQSYNTAX);
11952         varnest = 0;
11953         IF_FEATURE_SH_MATH(arinest = 0;)
11954         IF_FEATURE_SH_MATH(parenlevel = 0;)
11955         dqvarnest = 0;
11956
11957         STARTSTACKSTR(out);
11958  loop:
11959         /* For each line, until end of word */
11960         CHECKEND();     /* set c to PEOF if at end of here document */
11961         for (;;) {      /* until end of line or end of word */
11962                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11963                 switch (SIT(c, syntax)) {
11964                 case CNL:       /* '\n' */
11965                         if (syntax == BASESYNTAX)
11966                                 goto endword;   /* exit outer loop */
11967                         USTPUTC(c, out);
11968                         nlprompt();
11969                         c = pgetc();
11970                         goto loop;              /* continue outer loop */
11971                 case CWORD:
11972                         USTPUTC(c, out);
11973                         break;
11974                 case CCTL:
11975 #if BASH_DOLLAR_SQUOTE
11976                         if (c == '\\' && bash_dollar_squote) {
11977                                 c = decode_dollar_squote();
11978                                 if (c == '\0') {
11979                                         /* skip $'\000', $'\x00' (like bash) */
11980                                         break;
11981                                 }
11982                                 if (c & 0x100) {
11983                                         /* Unknown escape. Encode as '\z' */
11984                                         c = (unsigned char)c;
11985                                         if (eofmark == NULL || dblquote)
11986                                                 USTPUTC(CTLESC, out);
11987                                         USTPUTC('\\', out);
11988                                 }
11989                         }
11990 #endif
11991                         if (eofmark == NULL || dblquote)
11992                                 USTPUTC(CTLESC, out);
11993                         USTPUTC(c, out);
11994                         break;
11995                 case CBACK:     /* backslash */
11996                         c = pgetc_without_PEOA();
11997                         if (c == PEOF) {
11998                                 USTPUTC(CTLESC, out);
11999                                 USTPUTC('\\', out);
12000                                 pungetc();
12001                         } else if (c == '\n') {
12002                                 nlprompt();
12003                         } else {
12004                                 if (pssyntax && c == '$') {
12005                                         USTPUTC(CTLESC, out);
12006                                         USTPUTC('\\', out);
12007                                 }
12008                                 /* Backslash is retained if we are in "str"
12009                                  * and next char isn't dquote-special.
12010                                  */
12011                                 if (dblquote
12012                                  && c != '\\'
12013                                  && c != '`'
12014                                  && c != '$'
12015                                  && (c != '"' || eofmark != NULL)
12016                                 ) {
12017 //dash survives not doing USTPUTC(CTLESC), but merely by chance:
12018 //Example: "\z" gets encoded as "\<CTLESC>z".
12019 //rmescapes() then emits "\", "\z", protecting z from globbing.
12020 //But it's wrong, should protect _both_ from globbing:
12021 //everything in double quotes is not globbed.
12022 //Unlike dash, we have a fix in rmescapes() which emits bare "z"
12023 //for "<CTLESC>z" since "z" is not glob-special (else unicode may break),
12024 //and glob would see "\z" and eat "\". Thus:
12025                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12026                                         USTPUTC('\\', out);
12027                                 }
12028                                 USTPUTC(CTLESC, out);
12029                                 USTPUTC(c, out);
12030                                 quotef = 1;
12031                         }
12032                         break;
12033                 case CSQUOTE:
12034                         syntax = SQSYNTAX;
12035  quotemark:
12036                         if (eofmark == NULL) {
12037                                 USTPUTC(CTLQUOTEMARK, out);
12038                         }
12039                         break;
12040                 case CDQUOTE:
12041                         syntax = DQSYNTAX;
12042                         dblquote = 1;
12043                         goto quotemark;
12044                 case CENDQUOTE:
12045                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12046                         if (eofmark != NULL && varnest == 0) {
12047                                 USTPUTC(c, out);
12048                         } else {
12049                                 if (dqvarnest == 0) {
12050                                         syntax = BASESYNTAX;
12051                                         dblquote = 0;
12052                                 }
12053                                 quotef = 1;
12054                                 goto quotemark;
12055                         }
12056                         break;
12057                 case CVAR:      /* '$' */
12058                         PARSESUB();             /* parse substitution */
12059                         break;
12060                 case CENDVAR:   /* '}' */
12061                         if (varnest > 0) {
12062                                 varnest--;
12063                                 if (dqvarnest > 0) {
12064                                         dqvarnest--;
12065                                 }
12066                                 c = CTLENDVAR;
12067                         }
12068                         USTPUTC(c, out);
12069                         break;
12070 #if ENABLE_FEATURE_SH_MATH
12071                 case CLP:       /* '(' in arithmetic */
12072                         parenlevel++;
12073                         USTPUTC(c, out);
12074                         break;
12075                 case CRP:       /* ')' in arithmetic */
12076                         if (parenlevel > 0) {
12077                                 parenlevel--;
12078                         } else {
12079                                 if (pgetc_eatbnl() == ')') {
12080                                         c = CTLENDARI;
12081                                         if (--arinest == 0) {
12082                                                 syntax = prevsyntax;
12083                                         }
12084                                 } else {
12085                                         /*
12086                                          * unbalanced parens
12087                                          * (don't 2nd guess - no error)
12088                                          */
12089                                         pungetc();
12090                                 }
12091                         }
12092                         USTPUTC(c, out);
12093                         break;
12094 #endif
12095                 case CBQUOTE:   /* '`' */
12096                         PARSEBACKQOLD();
12097                         break;
12098                 case CENDFILE:
12099                         goto endword;           /* exit outer loop */
12100                 case CIGN:
12101                         break;
12102                 default:
12103                         if (varnest == 0) {
12104 #if BASH_REDIR_OUTPUT
12105                                 if (c == '&') {
12106 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12107                                         if (pgetc() == '>')
12108                                                 c = 0x100 + '>'; /* flag &> */
12109                                         pungetc();
12110                                 }
12111 #endif
12112                                 goto endword;   /* exit outer loop */
12113                         }
12114                         IF_ASH_ALIAS(if (c != PEOA))
12115                                 USTPUTC(c, out);
12116                 }
12117                 c = pgetc();
12118         } /* for (;;) */
12119  endword:
12120
12121 #if ENABLE_FEATURE_SH_MATH
12122         if (syntax == ARISYNTAX)
12123                 raise_error_syntax("missing '))'");
12124 #endif
12125         if (syntax != BASESYNTAX && eofmark == NULL)
12126                 raise_error_syntax("unterminated quoted string");
12127         if (varnest != 0) {
12128                 /* { */
12129                 raise_error_syntax("missing '}'");
12130         }
12131         USTPUTC('\0', out);
12132         len = out - (char *)stackblock();
12133         out = stackblock();
12134         if (eofmark == NULL) {
12135                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12136                  && quotef == 0
12137                 ) {
12138                         if (isdigit_str9(out)) {
12139                                 PARSEREDIR(); /* passed as params: out, c */
12140                                 lasttoken = TREDIR;
12141                                 return lasttoken;
12142                         }
12143                         /* else: non-number X seen, interpret it
12144                          * as "NNNX>file" = "NNNX >file" */
12145                 }
12146                 pungetc();
12147         }
12148         quoteflag = quotef;
12149         backquotelist = bqlist;
12150         grabstackblock(len);
12151         wordtext = out;
12152         lasttoken = TWORD;
12153         return lasttoken;
12154 /* end of readtoken routine */
12155
12156 /*
12157  * Check to see whether we are at the end of the here document.  When this
12158  * is called, c is set to the first character of the next input line.  If
12159  * we are at the end of the here document, this routine sets the c to PEOF.
12160  */
12161 checkend: {
12162         if (realeofmark(eofmark)) {
12163                 int markloc;
12164                 char *p;
12165
12166 #if ENABLE_ASH_ALIAS
12167                 if (c == PEOA)
12168                         c = pgetc_without_PEOA();
12169 #endif
12170                 if (striptabs) {
12171                         while (c == '\t') {
12172                                 c = pgetc_without_PEOA();
12173                         }
12174                 }
12175
12176                 markloc = out - (char *)stackblock();
12177                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12178                         if (c != *p)
12179                                 goto more_heredoc;
12180
12181                         c = pgetc_without_PEOA();
12182                 }
12183
12184                 if (c == '\n' || c == PEOF) {
12185                         c = PEOF;
12186                         g_parsefile->linno++;
12187                         needprompt = doprompt;
12188                 } else {
12189                         int len_here;
12190
12191  more_heredoc:
12192                         p = (char *)stackblock() + markloc + 1;
12193                         len_here = out - p;
12194
12195                         if (len_here) {
12196                                 len_here -= (c >= PEOF);
12197                                 c = p[-1];
12198
12199                                 if (len_here) {
12200                                         char *str;
12201
12202                                         str = alloca(len_here + 1);
12203                                         *(char *)mempcpy(str, p, len_here) = '\0';
12204
12205                                         pushstring(str, NULL);
12206                                 }
12207                         }
12208                 }
12209
12210                 STADJUST((char *)stackblock() + markloc - out, out);
12211         }
12212         goto checkend_return;
12213 }
12214
12215 /*
12216  * Parse a redirection operator.  The variable "out" points to a string
12217  * specifying the fd to be redirected.  The variable "c" contains the
12218  * first character of the redirection operator.
12219  */
12220 parseredir: {
12221         /* out is already checked to be a valid number or "" */
12222         int fd = (*out == '\0' ? -1 : atoi(out));
12223         union node *np;
12224
12225         np = stzalloc(sizeof(struct nfile));
12226         if (c == '>') {
12227                 np->nfile.fd = 1;
12228                 c = pgetc();
12229                 if (c == '>')
12230                         np->type = NAPPEND;
12231                 else if (c == '|')
12232                         np->type = NCLOBBER;
12233                 else if (c == '&')
12234                         np->type = NTOFD;
12235                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12236                 else {
12237                         np->type = NTO;
12238                         pungetc();
12239                 }
12240         }
12241 #if BASH_REDIR_OUTPUT
12242         else if (c == 0x100 + '>') { /* this flags &> redirection */
12243                 np->nfile.fd = 1;
12244                 pgetc(); /* this is '>', no need to check */
12245                 np->type = NTO2;
12246         }
12247 #endif
12248         else { /* c == '<' */
12249                 /*np->nfile.fd = 0; - stzalloc did it */
12250                 c = pgetc();
12251                 switch (c) {
12252                 case '<':
12253                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12254                                 np = stzalloc(sizeof(struct nhere));
12255                                 /*np->nfile.fd = 0; - stzalloc did it */
12256                         }
12257                         np->type = NHERE;
12258                         heredoc = stzalloc(sizeof(struct heredoc));
12259                         heredoc->here = np;
12260                         c = pgetc();
12261                         if (c == '-') {
12262                                 heredoc->striptabs = 1;
12263                         } else {
12264                                 /*heredoc->striptabs = 0; - stzalloc did it */
12265                                 pungetc();
12266                         }
12267                         break;
12268
12269                 case '&':
12270                         np->type = NFROMFD;
12271                         break;
12272
12273                 case '>':
12274                         np->type = NFROMTO;
12275                         break;
12276
12277                 default:
12278                         np->type = NFROM;
12279                         pungetc();
12280                         break;
12281                 }
12282         }
12283         if (fd >= 0)
12284                 np->nfile.fd = fd;
12285         redirnode = np;
12286         goto parseredir_return;
12287 }
12288
12289 /*
12290  * Parse a substitution.  At this point, we have read the dollar sign
12291  * and nothing else.
12292  */
12293
12294 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12295  * (assuming ascii char codes, as the original implementation did) */
12296 #define is_special(c) \
12297         (((unsigned)(c) - 33 < 32) \
12298                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12299 parsesub: {
12300         unsigned char subtype;
12301         int typeloc;
12302
12303         c = pgetc_eatbnl();
12304         if ((checkkwd & CHKEOFMARK)
12305          || c > 255 /* PEOA or PEOF */
12306          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12307         ) {
12308 #if BASH_DOLLAR_SQUOTE
12309                 if (syntax != DQSYNTAX && c == '\'')
12310                         bash_dollar_squote = 1;
12311                 else
12312 #endif
12313                         USTPUTC('$', out);
12314                 pungetc();
12315         } else if (c == '(') {
12316                 /* $(command) or $((arith)) */
12317                 if (pgetc_eatbnl() == '(') {
12318 #if ENABLE_FEATURE_SH_MATH
12319                         PARSEARITH();
12320 #else
12321                         raise_error_syntax("support for $((arith)) is disabled");
12322 #endif
12323                 } else {
12324                         pungetc();
12325                         PARSEBACKQNEW();
12326                 }
12327         } else {
12328                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12329                 USTPUTC(CTLVAR, out);
12330                 typeloc = out - (char *)stackblock();
12331                 STADJUST(1, out);
12332                 subtype = VSNORMAL;
12333                 if (c == '{') {
12334                         c = pgetc_eatbnl();
12335                         subtype = 0;
12336                 }
12337  varname:
12338                 if (is_name(c)) {
12339                         /* $[{[#]]NAME[}] */
12340                         do {
12341                                 STPUTC(c, out);
12342                                 c = pgetc_eatbnl();
12343                         } while (is_in_name(c));
12344                 } else if (isdigit(c)) {
12345                         /* $[{[#]]NUM[}] */
12346                         do {
12347                                 STPUTC(c, out);
12348                                 c = pgetc_eatbnl();
12349                         } while (isdigit(c));
12350                 } else {
12351                         /* $[{[#]]<specialchar>[}] */
12352                         int cc = c;
12353
12354                         c = pgetc_eatbnl();
12355                         if (!subtype && cc == '#') {
12356                                 subtype = VSLENGTH;
12357                                 if (c == '_' || isalnum(c))
12358                                         goto varname;
12359                                 cc = c;
12360                                 c = pgetc_eatbnl();
12361                                 if (cc == '}' || c != '}') {
12362                                         pungetc();
12363                                         subtype = 0;
12364                                         c = cc;
12365                                         cc = '#';
12366                                 }
12367                         }
12368
12369                         if (!is_special(cc)) {
12370                                 if (subtype == VSLENGTH)
12371                                         subtype = 0;
12372                                 goto badsub;
12373                         }
12374
12375                         USTPUTC(cc, out);
12376                 }
12377
12378                 if (c != '}' && subtype == VSLENGTH) {
12379                         /* ${#VAR didn't end with } */
12380                         goto badsub;
12381                 }
12382
12383                 if (subtype == 0) {
12384                         static const char types[] ALIGN1 = "}-+?=";
12385                         /* ${VAR...} but not $VAR or ${#VAR} */
12386                         /* c == first char after VAR */
12387                         switch (c) {
12388                         case ':':
12389                                 c = pgetc_eatbnl();
12390 #if BASH_SUBSTR
12391                                 /* This check is only needed to not misinterpret
12392                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12393                                  * constructs.
12394                                  */
12395                                 if (!strchr(types, c)) {
12396                                         subtype = VSSUBSTR;
12397                                         pungetc();
12398                                         break; /* "goto badsub" is bigger (!) */
12399                                 }
12400 #endif
12401                                 subtype = VSNUL;
12402                                 /*FALLTHROUGH*/
12403                         default: {
12404                                 const char *p = strchr(types, c);
12405                                 if (p == NULL)
12406                                         break;
12407                                 subtype |= p - types + VSNORMAL;
12408                                 break;
12409                         }
12410                         case '%':
12411                         case '#': {
12412                                 int cc = c;
12413                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12414                                 c = pgetc_eatbnl();
12415                                 if (c != cc)
12416                                         goto badsub;
12417                                 subtype++;
12418                                 break;
12419                         }
12420 #if BASH_PATTERN_SUBST
12421                         case '/':
12422                                 /* ${v/[/]pattern/repl} */
12423 //TODO: encode pattern and repl separately.
12424 // Currently ${v/$var_with_slash/repl} is horribly broken
12425                                 subtype = VSREPLACE;
12426                                 c = pgetc_eatbnl();
12427                                 if (c != '/')
12428                                         goto badsub;
12429                                 subtype++; /* VSREPLACEALL */
12430                                 break;
12431 #endif
12432                         }
12433                 } else {
12434  badsub:
12435                         pungetc();
12436                 }
12437                 ((unsigned char *)stackblock())[typeloc] = subtype;
12438                 if (subtype != VSNORMAL) {
12439                         varnest++;
12440                         if (dblquote)
12441                                 dqvarnest++;
12442                 }
12443                 STPUTC('=', out);
12444         }
12445         goto parsesub_return;
12446 }
12447
12448 /*
12449  * Called to parse command substitutions.  Newstyle is set if the command
12450  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12451  * list of commands (passed by reference), and savelen is the number of
12452  * characters on the top of the stack which must be preserved.
12453  */
12454 parsebackq: {
12455         struct nodelist **nlpp;
12456         union node *n;
12457         char *str;
12458         size_t savelen;
12459         smallint saveprompt = 0;
12460
12461         str = NULL;
12462         savelen = out - (char *)stackblock();
12463         if (savelen > 0) {
12464                 /*
12465                  * FIXME: this can allocate very large block on stack and SEGV.
12466                  * Example:
12467                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12468                  * allocates 100kb for every command subst. With about
12469                  * a hundred command substitutions stack overflows.
12470                  * With larger prepended string, SEGV happens sooner.
12471                  */
12472                 str = alloca(savelen);
12473                 memcpy(str, stackblock(), savelen);
12474         }
12475
12476         if (oldstyle) {
12477                 /* We must read until the closing backquote, giving special
12478                  * treatment to some slashes, and then push the string and
12479                  * reread it as input, interpreting it normally.
12480                  */
12481                 char *pout;
12482                 size_t psavelen;
12483                 char *pstr;
12484
12485                 STARTSTACKSTR(pout);
12486                 for (;;) {
12487                         int pc;
12488
12489                         setprompt_if(needprompt, 2);
12490                         pc = pgetc();
12491                         switch (pc) {
12492                         case '`':
12493                                 goto done;
12494
12495                         case '\\':
12496                                 pc = pgetc();
12497                                 if (pc == '\n') {
12498                                         nlprompt();
12499                                         /*
12500                                          * If eating a newline, avoid putting
12501                                          * the newline into the new character
12502                                          * stream (via the STPUTC after the
12503                                          * switch).
12504                                          */
12505                                         continue;
12506                                 }
12507                                 if (pc != '\\' && pc != '`' && pc != '$'
12508                                  && (!dblquote || pc != '"')
12509                                 ) {
12510                                         STPUTC('\\', pout);
12511                                 }
12512                                 if (pc <= 255 /* not PEOA or PEOF */) {
12513                                         break;
12514                                 }
12515                                 /* fall through */
12516
12517                         case PEOF:
12518                         IF_ASH_ALIAS(case PEOA:)
12519                                 raise_error_syntax("EOF in backquote substitution");
12520
12521                         case '\n':
12522                                 nlnoprompt();
12523                                 break;
12524
12525                         default:
12526                                 break;
12527                         }
12528                         STPUTC(pc, pout);
12529                 }
12530  done:
12531                 STPUTC('\0', pout);
12532                 psavelen = pout - (char *)stackblock();
12533                 if (psavelen > 0) {
12534                         pstr = grabstackstr(pout);
12535                         setinputstring(pstr);
12536                 }
12537         }
12538         nlpp = &bqlist;
12539         while (*nlpp)
12540                 nlpp = &(*nlpp)->next;
12541         *nlpp = stzalloc(sizeof(**nlpp));
12542         /* (*nlpp)->next = NULL; - stzalloc did it */
12543
12544         if (oldstyle) {
12545                 saveprompt = doprompt;
12546                 doprompt = 0;
12547         }
12548
12549         n = list(2);
12550
12551         if (oldstyle)
12552                 doprompt = saveprompt;
12553         else if (readtoken() != TRP)
12554                 raise_error_unexpected_syntax(TRP);
12555
12556         (*nlpp)->n = n;
12557         if (oldstyle) {
12558                 /*
12559                  * Start reading from old file again, ignoring any pushed back
12560                  * tokens left from the backquote parsing
12561                  */
12562                 popfile();
12563                 tokpushback = 0;
12564         }
12565         while (stackblocksize() <= savelen)
12566                 growstackblock();
12567         STARTSTACKSTR(out);
12568         if (str) {
12569                 memcpy(out, str, savelen);
12570                 STADJUST(savelen, out);
12571         }
12572         USTPUTC(CTLBACKQ, out);
12573         if (oldstyle)
12574                 goto parsebackq_oldreturn;
12575         goto parsebackq_newreturn;
12576 }
12577
12578 #if ENABLE_FEATURE_SH_MATH
12579 /*
12580  * Parse an arithmetic expansion (indicate start of one and set state)
12581  */
12582 parsearith: {
12583         if (++arinest == 1) {
12584                 prevsyntax = syntax;
12585                 syntax = ARISYNTAX;
12586         }
12587         USTPUTC(CTLARI, out);
12588         goto parsearith_return;
12589 }
12590 #endif
12591 } /* end of readtoken */
12592
12593 /*
12594  * Read the next input token.
12595  * If the token is a word, we set backquotelist to the list of cmds in
12596  *      backquotes.  We set quoteflag to true if any part of the word was
12597  *      quoted.
12598  * If the token is TREDIR, then we set redirnode to a structure containing
12599  *      the redirection.
12600  *
12601  * [Change comment:  here documents and internal procedures]
12602  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12603  *  word parsing code into a separate routine.  In this case, readtoken
12604  *  doesn't need to have any internal procedures, but parseword does.
12605  *  We could also make parseoperator in essence the main routine, and
12606  *  have parseword (readtoken1?) handle both words and redirection.]
12607  */
12608 #define NEW_xxreadtoken
12609 #ifdef NEW_xxreadtoken
12610 /* singles must be first! */
12611 static const char xxreadtoken_chars[7] ALIGN1 = {
12612         '\n', '(', ')', /* singles */
12613         '&', '|', ';',  /* doubles */
12614         0
12615 };
12616
12617 #define xxreadtoken_singles 3
12618 #define xxreadtoken_doubles 3
12619
12620 static const char xxreadtoken_tokens[] ALIGN1 = {
12621         TNL, TLP, TRP,          /* only single occurrence allowed */
12622         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12623         TEOF,                   /* corresponds to trailing nul */
12624         TAND, TOR, TENDCASE     /* if double occurrence */
12625 };
12626
12627 static int
12628 xxreadtoken(void)
12629 {
12630         int c;
12631
12632         if (tokpushback) {
12633                 tokpushback = 0;
12634                 return lasttoken;
12635         }
12636         setprompt_if(needprompt, 2);
12637         for (;;) {                      /* until token or start of word found */
12638                 c = pgetc();
12639                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12640                         continue;
12641
12642                 if (c == '#') {
12643                         while ((c = pgetc()) != '\n' && c != PEOF)
12644                                 continue;
12645                         pungetc();
12646                 } else if (c == '\\') {
12647                         if (pgetc() != '\n') {
12648                                 pungetc();
12649                                 break; /* return readtoken1(...) */
12650                         }
12651                         nlprompt();
12652                 } else {
12653                         const char *p;
12654
12655                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12656                         if (c != PEOF) {
12657                                 if (c == '\n') {
12658                                         nlnoprompt();
12659                                 }
12660
12661                                 p = strchr(xxreadtoken_chars, c);
12662                                 if (p == NULL)
12663                                         break; /* return readtoken1(...) */
12664
12665                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12666                                         int cc = pgetc();
12667                                         if (cc == c) {    /* double occurrence? */
12668                                                 p += xxreadtoken_doubles + 1;
12669                                         } else {
12670                                                 pungetc();
12671 #if BASH_REDIR_OUTPUT
12672                                                 if (c == '&' && cc == '>') /* &> */
12673                                                         break; /* return readtoken1(...) */
12674 #endif
12675                                         }
12676                                 }
12677                         }
12678                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12679                         return lasttoken;
12680                 }
12681         } /* for (;;) */
12682
12683         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12684 }
12685 #else /* old xxreadtoken */
12686 #define RETURN(token)   return lasttoken = token
12687 static int
12688 xxreadtoken(void)
12689 {
12690         int c;
12691
12692         if (tokpushback) {
12693                 tokpushback = 0;
12694                 return lasttoken;
12695         }
12696         setprompt_if(needprompt, 2);
12697         for (;;) {      /* until token or start of word found */
12698                 c = pgetc();
12699                 switch (c) {
12700                 case ' ': case '\t':
12701                 IF_ASH_ALIAS(case PEOA:)
12702                         continue;
12703                 case '#':
12704                         while ((c = pgetc()) != '\n' && c != PEOF)
12705                                 continue;
12706                         pungetc();
12707                         continue;
12708                 case '\\':
12709                         if (pgetc() == '\n') {
12710                                 nlprompt();
12711                                 continue;
12712                         }
12713                         pungetc();
12714                         goto breakloop;
12715                 case '\n':
12716                         nlnoprompt();
12717                         RETURN(TNL);
12718                 case PEOF:
12719                         RETURN(TEOF);
12720                 case '&':
12721                         if (pgetc() == '&')
12722                                 RETURN(TAND);
12723                         pungetc();
12724                         RETURN(TBACKGND);
12725                 case '|':
12726                         if (pgetc() == '|')
12727                                 RETURN(TOR);
12728                         pungetc();
12729                         RETURN(TPIPE);
12730                 case ';':
12731                         if (pgetc() == ';')
12732                                 RETURN(TENDCASE);
12733                         pungetc();
12734                         RETURN(TSEMI);
12735                 case '(':
12736                         RETURN(TLP);
12737                 case ')':
12738                         RETURN(TRP);
12739                 default:
12740                         goto breakloop;
12741                 }
12742         }
12743  breakloop:
12744         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12745 #undef RETURN
12746 }
12747 #endif /* old xxreadtoken */
12748
12749 static int
12750 readtoken(void)
12751 {
12752         int t;
12753         int kwd = checkkwd;
12754 #if DEBUG
12755         smallint alreadyseen = tokpushback;
12756 #endif
12757
12758 #if ENABLE_ASH_ALIAS
12759  top:
12760 #endif
12761
12762         t = xxreadtoken();
12763
12764         /*
12765          * eat newlines
12766          */
12767         if (kwd & CHKNL) {
12768                 while (t == TNL) {
12769                         parseheredoc();
12770                         t = xxreadtoken();
12771                 }
12772         }
12773
12774         if (t != TWORD || quoteflag) {
12775                 goto out;
12776         }
12777
12778         /*
12779          * check for keywords
12780          */
12781         if (kwd & CHKKWD) {
12782                 const char *const *pp;
12783
12784                 pp = findkwd(wordtext);
12785                 if (pp) {
12786                         lasttoken = t = pp - tokname_array;
12787                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12788                         goto out;
12789                 }
12790         }
12791
12792         if (checkkwd & CHKALIAS) {
12793 #if ENABLE_ASH_ALIAS
12794                 struct alias *ap;
12795                 ap = lookupalias(wordtext, 1);
12796                 if (ap != NULL) {
12797                         if (*ap->val) {
12798                                 pushstring(ap->val, ap);
12799                         }
12800                         goto top;
12801                 }
12802 #endif
12803         }
12804  out:
12805         checkkwd = 0;
12806 #if DEBUG
12807         if (!alreadyseen)
12808                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12809         else
12810                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12811 #endif
12812         return t;
12813 }
12814
12815 static int
12816 peektoken(void)
12817 {
12818         int t;
12819
12820         t = readtoken();
12821         tokpushback = 1;
12822         return t;
12823 }
12824
12825 /*
12826  * Read and parse a command.  Returns NODE_EOF on end of file.
12827  * (NULL is a valid parse tree indicating a blank line.)
12828  */
12829 static union node *
12830 parsecmd(int interact)
12831 {
12832         tokpushback = 0;
12833         checkkwd = 0;
12834         heredoclist = 0;
12835         doprompt = interact;
12836         setprompt_if(doprompt, doprompt);
12837         needprompt = 0;
12838         return list(1);
12839 }
12840
12841 /*
12842  * Input any here documents.
12843  */
12844 static void
12845 parseheredoc(void)
12846 {
12847         struct heredoc *here;
12848         union node *n;
12849
12850         here = heredoclist;
12851         heredoclist = NULL;
12852
12853         while (here) {
12854                 setprompt_if(needprompt, 2);
12855                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12856                                 here->eofmark, here->striptabs);
12857                 n = stzalloc(sizeof(struct narg));
12858                 n->narg.type = NARG;
12859                 /*n->narg.next = NULL; - stzalloc did it */
12860                 n->narg.text = wordtext;
12861                 n->narg.backquote = backquotelist;
12862                 here->here->nhere.doc = n;
12863                 here = here->next;
12864         }
12865 }
12866
12867
12868 static const char *
12869 expandstr(const char *ps, int syntax_type)
12870 {
12871         union node n;
12872         int saveprompt;
12873
12874         /* XXX Fix (char *) cast. */
12875         setinputstring((char *)ps);
12876
12877         saveprompt = doprompt;
12878         doprompt = 0;
12879
12880         /* readtoken1() might die horribly.
12881          * Try a prompt with syntactically wrong command:
12882          * PS1='$(date "+%H:%M:%S) > '
12883          */
12884         {
12885                 volatile int saveint;
12886                 struct jmploc *volatile savehandler = exception_handler;
12887                 struct jmploc jmploc;
12888                 SAVE_INT(saveint);
12889                 if (setjmp(jmploc.loc) == 0) {
12890                         exception_handler = &jmploc;
12891                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12892                 }
12893                 exception_handler = savehandler;
12894                 RESTORE_INT(saveint);
12895         }
12896
12897         doprompt = saveprompt;
12898
12899         popfile();
12900
12901         n.narg.type = NARG;
12902         n.narg.next = NULL;
12903         n.narg.text = wordtext;
12904         n.narg.backquote = backquotelist;
12905
12906         expandarg(&n, NULL, EXP_QUOTED);
12907         return stackblock();
12908 }
12909
12910 static inline int
12911 parser_eof(void)
12912 {
12913         return tokpushback && lasttoken == TEOF;
12914 }
12915
12916 /*
12917  * Execute a command or commands contained in a string.
12918  */
12919 static int
12920 evalstring(char *s, int flags)
12921 {
12922         struct jmploc *volatile savehandler;
12923         struct jmploc jmploc;
12924         int ex;
12925
12926         union node *n;
12927         struct stackmark smark;
12928         int status;
12929
12930         s = sstrdup(s);
12931         setinputstring(s);
12932         setstackmark(&smark);
12933
12934         status = 0;
12935         /* On exception inside execution loop, we must popfile().
12936          * Try interactively:
12937          *      readonly a=a
12938          *      command eval "a=b"  # throws "is read only" error
12939          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12940          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12941          */
12942         savehandler = exception_handler;
12943         ex = setjmp(jmploc.loc);
12944         if (ex)
12945                 goto out;
12946         exception_handler = &jmploc;
12947
12948         while ((n = parsecmd(0)) != NODE_EOF) {
12949                 int i;
12950
12951                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12952                 if (n)
12953                         status = i;
12954                 popstackmark(&smark);
12955                 if (evalskip)
12956                         break;
12957         }
12958  out:
12959         popstackmark(&smark);
12960         popfile();
12961         stunalloc(s);
12962
12963         exception_handler = savehandler;
12964         if (ex)
12965                 longjmp(exception_handler->loc, ex);
12966
12967         return status;
12968 }
12969
12970 /*
12971  * The eval command.
12972  */
12973 static int FAST_FUNC
12974 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12975 {
12976         char *p;
12977         char *concat;
12978
12979         if (argv[1]) {
12980                 p = argv[1];
12981                 argv += 2;
12982                 if (argv[0]) {
12983                         STARTSTACKSTR(concat);
12984                         for (;;) {
12985                                 concat = stack_putstr(p, concat);
12986                                 p = *argv++;
12987                                 if (p == NULL)
12988                                         break;
12989                                 STPUTC(' ', concat);
12990                         }
12991                         STPUTC('\0', concat);
12992                         p = grabstackstr(concat);
12993                 }
12994                 return evalstring(p, flags & EV_TESTED);
12995         }
12996         return 0;
12997 }
12998
12999 /*
13000  * Read and execute commands.
13001  * "Top" is nonzero for the top level command loop;
13002  * it turns on prompting if the shell is interactive.
13003  */
13004 static int
13005 cmdloop(int top)
13006 {
13007         union node *n;
13008         struct stackmark smark;
13009         int inter;
13010         int status = 0;
13011         int numeof = 0;
13012
13013         TRACE(("cmdloop(%d) called\n", top));
13014         for (;;) {
13015                 int skip;
13016
13017                 setstackmark(&smark);
13018 #if JOBS
13019                 if (doing_jobctl)
13020                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13021 #endif
13022                 inter = 0;
13023                 if (iflag && top) {
13024                         inter++;
13025                         chkmail();
13026                 }
13027                 n = parsecmd(inter);
13028 #if DEBUG
13029                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13030                         showtree(n);
13031 #endif
13032                 if (n == NODE_EOF) {
13033                         if (!top || numeof >= 50)
13034                                 break;
13035                         if (!stoppedjobs()) {
13036                                 if (!Iflag)
13037                                         break;
13038                                 out2str("\nUse \"exit\" to leave shell.\n");
13039                         }
13040                         numeof++;
13041                 } else if (nflag == 0) {
13042                         int i;
13043
13044                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13045                         job_warning >>= 1;
13046                         numeof = 0;
13047                         i = evaltree(n, 0);
13048                         if (n)
13049                                 status = i;
13050                 }
13051                 popstackmark(&smark);
13052                 skip = evalskip;
13053
13054                 if (skip) {
13055                         evalskip &= ~SKIPFUNC;
13056                         break;
13057                 }
13058         }
13059         return status;
13060 }
13061
13062 /*
13063  * Take commands from a file.  To be compatible we should do a path
13064  * search for the file, which is necessary to find sub-commands.
13065  */
13066 static char *
13067 find_dot_file(char *name)
13068 {
13069         char *fullname;
13070         const char *path = pathval();
13071         struct stat statb;
13072
13073         /* don't try this for absolute or relative paths */
13074         if (strchr(name, '/'))
13075                 return name;
13076
13077         while ((fullname = path_advance(&path, name)) != NULL) {
13078                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13079                         /*
13080                          * Don't bother freeing here, since it will
13081                          * be freed by the caller.
13082                          */
13083                         return fullname;
13084                 }
13085                 if (fullname != name)
13086                         stunalloc(fullname);
13087         }
13088         /* not found in PATH */
13089
13090 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13091         return name;
13092 #else
13093         ash_msg_and_raise_error("%s: not found", name);
13094         /* NOTREACHED */
13095 #endif
13096 }
13097
13098 static int FAST_FUNC
13099 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13100 {
13101         /* "false; . empty_file; echo $?" should print 0, not 1: */
13102         int status = 0;
13103         char *fullname;
13104         char **argv;
13105         char *args_need_save;
13106         volatile struct shparam saveparam;
13107
13108 //???
13109 //      struct strlist *sp;
13110 //      for (sp = cmdenviron; sp; sp = sp->next)
13111 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13112
13113         nextopt(nullstr); /* handle possible "--" */
13114         argv = argptr;
13115
13116         if (!argv[0]) {
13117                 /* bash says: "bash: .: filename argument required" */
13118                 return 2; /* bash compat */
13119         }
13120
13121         /* This aborts if file isn't found, which is POSIXly correct.
13122          * bash returns exitcode 1 instead.
13123          */
13124         fullname = find_dot_file(argv[0]);
13125         argv++;
13126         args_need_save = argv[0];
13127         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13128                 int argc;
13129                 saveparam = shellparam;
13130                 shellparam.malloced = 0;
13131                 argc = 1;
13132                 while (argv[argc])
13133                         argc++;
13134                 shellparam.nparam = argc;
13135                 shellparam.p = argv;
13136         };
13137
13138         /* This aborts if file can't be opened, which is POSIXly correct.
13139          * bash returns exitcode 1 instead.
13140          */
13141         setinputfile(fullname, INPUT_PUSH_FILE);
13142         commandname = fullname;
13143         status = cmdloop(0);
13144         popfile();
13145
13146         if (args_need_save) {
13147                 freeparam(&shellparam);
13148                 shellparam = saveparam;
13149         };
13150
13151         return status;
13152 }
13153
13154 static int FAST_FUNC
13155 exitcmd(int argc UNUSED_PARAM, char **argv)
13156 {
13157         if (stoppedjobs())
13158                 return 0;
13159         if (argv[1])
13160                 exitstatus = number(argv[1]);
13161         raise_exception(EXEXIT);
13162         /* NOTREACHED */
13163 }
13164
13165 /*
13166  * Read a file containing shell functions.
13167  */
13168 static void
13169 readcmdfile(char *name)
13170 {
13171         setinputfile(name, INPUT_PUSH_FILE);
13172         cmdloop(0);
13173         popfile();
13174 }
13175
13176
13177 /* ============ find_command inplementation */
13178
13179 /*
13180  * Resolve a command name.  If you change this routine, you may have to
13181  * change the shellexec routine as well.
13182  */
13183 static void
13184 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13185 {
13186         struct tblentry *cmdp;
13187         int idx;
13188         int prev;
13189         char *fullname;
13190         struct stat statb;
13191         int e;
13192         int updatetbl;
13193         struct builtincmd *bcmd;
13194
13195         /* If name contains a slash, don't use PATH or hash table */
13196         if (strchr(name, '/') != NULL) {
13197                 entry->u.index = -1;
13198                 if (act & DO_ABS) {
13199                         while (stat(name, &statb) < 0) {
13200 #ifdef SYSV
13201                                 if (errno == EINTR)
13202                                         continue;
13203 #endif
13204                                 entry->cmdtype = CMDUNKNOWN;
13205                                 return;
13206                         }
13207                 }
13208                 entry->cmdtype = CMDNORMAL;
13209                 return;
13210         }
13211
13212 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13213
13214         updatetbl = (path == pathval());
13215         if (!updatetbl) {
13216                 act |= DO_ALTPATH;
13217                 if (strstr(path, "%builtin") != NULL)
13218                         act |= DO_ALTBLTIN;
13219         }
13220
13221         /* If name is in the table, check answer will be ok */
13222         cmdp = cmdlookup(name, 0);
13223         if (cmdp != NULL) {
13224                 int bit;
13225
13226                 switch (cmdp->cmdtype) {
13227                 default:
13228 #if DEBUG
13229                         abort();
13230 #endif
13231                 case CMDNORMAL:
13232                         bit = DO_ALTPATH;
13233                         break;
13234                 case CMDFUNCTION:
13235                         bit = DO_NOFUNC;
13236                         break;
13237                 case CMDBUILTIN:
13238                         bit = DO_ALTBLTIN;
13239                         break;
13240                 }
13241                 if (act & bit) {
13242                         updatetbl = 0;
13243                         cmdp = NULL;
13244                 } else if (cmdp->rehash == 0)
13245                         /* if not invalidated by cd, we're done */
13246                         goto success;
13247         }
13248
13249         /* If %builtin not in path, check for builtin next */
13250         bcmd = find_builtin(name);
13251         if (bcmd) {
13252                 if (IS_BUILTIN_REGULAR(bcmd))
13253                         goto builtin_success;
13254                 if (act & DO_ALTPATH) {
13255                         if (!(act & DO_ALTBLTIN))
13256                                 goto builtin_success;
13257                 } else if (builtinloc <= 0) {
13258                         goto builtin_success;
13259                 }
13260         }
13261
13262 #if ENABLE_FEATURE_SH_STANDALONE
13263         {
13264                 int applet_no = find_applet_by_name(name);
13265                 if (applet_no >= 0) {
13266                         entry->cmdtype = CMDNORMAL;
13267                         entry->u.index = -2 - applet_no;
13268                         return;
13269                 }
13270         }
13271 #endif
13272
13273         /* We have to search path. */
13274         prev = -1;              /* where to start */
13275         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13276                 if (cmdp->cmdtype == CMDBUILTIN)
13277                         prev = builtinloc;
13278                 else
13279                         prev = cmdp->param.index;
13280         }
13281
13282         e = ENOENT;
13283         idx = -1;
13284  loop:
13285         while ((fullname = path_advance(&path, name)) != NULL) {
13286                 stunalloc(fullname);
13287                 /* NB: code below will still use fullname
13288                  * despite it being "unallocated" */
13289                 idx++;
13290                 if (pathopt) {
13291                         if (prefix(pathopt, "builtin")) {
13292                                 if (bcmd)
13293                                         goto builtin_success;
13294                                 continue;
13295                         }
13296                         if ((act & DO_NOFUNC)
13297                          || !prefix(pathopt, "func")
13298                         ) {     /* ignore unimplemented options */
13299                                 continue;
13300                         }
13301                 }
13302                 /* if rehash, don't redo absolute path names */
13303                 if (fullname[0] == '/' && idx <= prev) {
13304                         if (idx < prev)
13305                                 continue;
13306                         TRACE(("searchexec \"%s\": no change\n", name));
13307                         goto success;
13308                 }
13309                 while (stat(fullname, &statb) < 0) {
13310 #ifdef SYSV
13311                         if (errno == EINTR)
13312                                 continue;
13313 #endif
13314                         if (errno != ENOENT && errno != ENOTDIR)
13315                                 e = errno;
13316                         goto loop;
13317                 }
13318                 e = EACCES;     /* if we fail, this will be the error */
13319                 if (!S_ISREG(statb.st_mode))
13320                         continue;
13321                 if (pathopt) {          /* this is a %func directory */
13322                         stalloc(strlen(fullname) + 1);
13323                         /* NB: stalloc will return space pointed by fullname
13324                          * (because we don't have any intervening allocations
13325                          * between stunalloc above and this stalloc) */
13326                         readcmdfile(fullname);
13327                         cmdp = cmdlookup(name, 0);
13328                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13329                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13330                         stunalloc(fullname);
13331                         goto success;
13332                 }
13333                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13334                 if (!updatetbl) {
13335                         entry->cmdtype = CMDNORMAL;
13336                         entry->u.index = idx;
13337                         return;
13338                 }
13339                 INT_OFF;
13340                 cmdp = cmdlookup(name, 1);
13341                 cmdp->cmdtype = CMDNORMAL;
13342                 cmdp->param.index = idx;
13343                 INT_ON;
13344                 goto success;
13345         }
13346
13347         /* We failed.  If there was an entry for this command, delete it */
13348         if (cmdp && updatetbl)
13349                 delete_cmd_entry();
13350         if (act & DO_ERR) {
13351 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13352                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13353                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13354                         char *argv[3];
13355                         argv[0] = (char*) "command_not_found_handle";
13356                         argv[1] = name;
13357                         argv[2] = NULL;
13358                         evalfun(hookp->param.func, 2, argv, 0);
13359                         entry->cmdtype = CMDUNKNOWN;
13360                         return;
13361                 }
13362 #endif
13363                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13364         }
13365         entry->cmdtype = CMDUNKNOWN;
13366         return;
13367
13368  builtin_success:
13369         if (!updatetbl) {
13370                 entry->cmdtype = CMDBUILTIN;
13371                 entry->u.cmd = bcmd;
13372                 return;
13373         }
13374         INT_OFF;
13375         cmdp = cmdlookup(name, 1);
13376         cmdp->cmdtype = CMDBUILTIN;
13377         cmdp->param.cmd = bcmd;
13378         INT_ON;
13379  success:
13380         cmdp->rehash = 0;
13381         entry->cmdtype = cmdp->cmdtype;
13382         entry->u = cmdp->param;
13383 }
13384
13385
13386 /*
13387  * The trap builtin.
13388  */
13389 static int FAST_FUNC
13390 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13391 {
13392         char *action;
13393         char **ap;
13394         int signo, exitcode;
13395
13396         nextopt(nullstr);
13397         ap = argptr;
13398         if (!*ap) {
13399                 for (signo = 0; signo < NSIG; signo++) {
13400                         char *tr = trap_ptr[signo];
13401                         if (tr) {
13402                                 /* note: bash adds "SIG", but only if invoked
13403                                  * as "bash". If called as "sh", or if set -o posix,
13404                                  * then it prints short signal names.
13405                                  * We are printing short names: */
13406                                 out1fmt("trap -- %s %s\n",
13407                                                 single_quote(tr),
13408                                                 get_signame(signo));
13409                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13410                  * In this case, we will exit very soon, no need to free(). */
13411                                 /* if (trap_ptr != trap && tp[0]) */
13412                                 /*      free(tr); */
13413                         }
13414                 }
13415                 /*
13416                 if (trap_ptr != trap) {
13417                         free(trap_ptr);
13418                         trap_ptr = trap;
13419                 }
13420                 */
13421                 return 0;
13422         }
13423
13424         /* Why the second check?
13425          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13426          * In this case, NUM is signal no, not an action.
13427          */
13428         action = NULL;
13429         if (ap[1] && !is_number(ap[0]))
13430                 action = *ap++;
13431
13432         exitcode = 0;
13433         while (*ap) {
13434                 signo = get_signum(*ap);
13435                 if (signo < 0) {
13436                         /* Mimic bash message exactly */
13437                         ash_msg("%s: invalid signal specification", *ap);
13438                         exitcode = 1;
13439                         goto next;
13440                 }
13441                 INT_OFF;
13442                 if (action) {
13443                         if (LONE_DASH(action))
13444                                 action = NULL;
13445                         else {
13446                                 if (action[0]) /* not NULL and not "" and not "-" */
13447                                         may_have_traps = 1;
13448                                 action = ckstrdup(action);
13449                         }
13450                 }
13451                 free(trap[signo]);
13452                 trap[signo] = action;
13453                 if (signo != 0)
13454                         setsignal(signo);
13455                 INT_ON;
13456  next:
13457                 ap++;
13458         }
13459         return exitcode;
13460 }
13461
13462
13463 /* ============ Builtins */
13464
13465 #if ENABLE_ASH_HELP
13466 static int FAST_FUNC
13467 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13468 {
13469         unsigned col;
13470         unsigned i;
13471
13472         out1fmt(
13473                 "Built-in commands:\n"
13474                 "------------------\n");
13475         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13476                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13477                                         builtintab[i].name + 1);
13478                 if (col > 60) {
13479                         out1fmt("\n");
13480                         col = 0;
13481                 }
13482         }
13483 # if ENABLE_FEATURE_SH_STANDALONE
13484         {
13485                 const char *a = applet_names;
13486                 while (*a) {
13487                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13488                         if (col > 60) {
13489                                 out1fmt("\n");
13490                                 col = 0;
13491                         }
13492                         while (*a++ != '\0')
13493                                 continue;
13494                 }
13495         }
13496 # endif
13497         newline_and_flush(stdout);
13498         return EXIT_SUCCESS;
13499 }
13500 #endif
13501
13502 #if MAX_HISTORY
13503 static int FAST_FUNC
13504 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13505 {
13506         show_history(line_input_state);
13507         return EXIT_SUCCESS;
13508 }
13509 #endif
13510
13511 /*
13512  * The export and readonly commands.
13513  */
13514 static int FAST_FUNC
13515 exportcmd(int argc UNUSED_PARAM, char **argv)
13516 {
13517         struct var *vp;
13518         char *name;
13519         const char *p;
13520         char **aptr;
13521         char opt;
13522         int flag;
13523         int flag_off;
13524
13525         /* "readonly" in bash accepts, but ignores -n.
13526          * We do the same: it saves a conditional in nextopt's param.
13527          */
13528         flag_off = 0;
13529         while ((opt = nextopt("np")) != '\0') {
13530                 if (opt == 'n')
13531                         flag_off = VEXPORT;
13532         }
13533         flag = VEXPORT;
13534         if (argv[0][0] == 'r') {
13535                 flag = VREADONLY;
13536                 flag_off = 0; /* readonly ignores -n */
13537         }
13538         flag_off = ~flag_off;
13539
13540         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13541         {
13542                 aptr = argptr;
13543                 name = *aptr;
13544                 if (name) {
13545                         do {
13546                                 p = strchr(name, '=');
13547                                 if (p != NULL) {
13548                                         p++;
13549                                 } else {
13550                                         vp = *findvar(hashvar(name), name);
13551                                         if (vp) {
13552                                                 vp->flags = ((vp->flags | flag) & flag_off);
13553                                                 continue;
13554                                         }
13555                                 }
13556                                 setvar(name, p, (flag & flag_off));
13557                         } while ((name = *++aptr) != NULL);
13558                         return 0;
13559                 }
13560         }
13561
13562         /* No arguments. Show the list of exported or readonly vars.
13563          * -n is ignored.
13564          */
13565         showvars(argv[0], flag, 0);
13566         return 0;
13567 }
13568
13569 /*
13570  * Delete a function if it exists.
13571  */
13572 static void
13573 unsetfunc(const char *name)
13574 {
13575         struct tblentry *cmdp;
13576
13577         cmdp = cmdlookup(name, 0);
13578         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13579                 delete_cmd_entry();
13580 }
13581
13582 /*
13583  * The unset builtin command.  We unset the function before we unset the
13584  * variable to allow a function to be unset when there is a readonly variable
13585  * with the same name.
13586  */
13587 static int FAST_FUNC
13588 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13589 {
13590         char **ap;
13591         int i;
13592         int flag = 0;
13593
13594         while ((i = nextopt("vf")) != 0) {
13595                 flag = i;
13596         }
13597
13598         for (ap = argptr; *ap; ap++) {
13599                 if (flag != 'f') {
13600                         unsetvar(*ap);
13601                         continue;
13602                 }
13603                 if (flag != 'v')
13604                         unsetfunc(*ap);
13605         }
13606         return 0;
13607 }
13608
13609 static const unsigned char timescmd_str[] ALIGN1 = {
13610         ' ',  offsetof(struct tms, tms_utime),
13611         '\n', offsetof(struct tms, tms_stime),
13612         ' ',  offsetof(struct tms, tms_cutime),
13613         '\n', offsetof(struct tms, tms_cstime),
13614         0
13615 };
13616 static int FAST_FUNC
13617 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13618 {
13619         unsigned clk_tck;
13620         const unsigned char *p;
13621         struct tms buf;
13622
13623         clk_tck = bb_clk_tck();
13624
13625         times(&buf);
13626         p = timescmd_str;
13627         do {
13628                 unsigned sec, frac;
13629                 unsigned long t;
13630                 t = *(clock_t *)(((char *) &buf) + p[1]);
13631                 sec = t / clk_tck;
13632                 frac = t % clk_tck;
13633                 out1fmt("%um%u.%03us%c",
13634                         sec / 60, sec % 60,
13635                         (frac * 1000) / clk_tck,
13636                         p[0]);
13637                 p += 2;
13638         } while (*p);
13639
13640         return 0;
13641 }
13642
13643 #if ENABLE_FEATURE_SH_MATH
13644 /*
13645  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13646  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13647  *
13648  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13649  */
13650 static int FAST_FUNC
13651 letcmd(int argc UNUSED_PARAM, char **argv)
13652 {
13653         arith_t i;
13654
13655         argv++;
13656         if (!*argv)
13657                 ash_msg_and_raise_error("expression expected");
13658         do {
13659                 i = ash_arith(*argv);
13660         } while (*++argv);
13661
13662         return !i;
13663 }
13664 #endif
13665
13666 /*
13667  * The read builtin. Options:
13668  *      -r              Do not interpret '\' specially
13669  *      -s              Turn off echo (tty only)
13670  *      -n NCHARS       Read NCHARS max
13671  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13672  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13673  *      -u FD           Read from given FD instead of fd 0
13674  *      -d DELIM        End on DELIM char, not newline
13675  * This uses unbuffered input, which may be avoidable in some cases.
13676  * TODO: bash also has:
13677  *      -a ARRAY        Read into array[0],[1],etc
13678  *      -e              Use line editing (tty only)
13679  */
13680 static int FAST_FUNC
13681 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13682 {
13683         char *opt_n = NULL;
13684         char *opt_p = NULL;
13685         char *opt_t = NULL;
13686         char *opt_u = NULL;
13687         char *opt_d = NULL; /* optimized out if !BASH */
13688         int read_flags = 0;
13689         const char *r;
13690         int i;
13691
13692         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13693                 switch (i) {
13694                 case 'p':
13695                         opt_p = optionarg;
13696                         break;
13697                 case 'n':
13698                         opt_n = optionarg;
13699                         break;
13700                 case 's':
13701                         read_flags |= BUILTIN_READ_SILENT;
13702                         break;
13703                 case 't':
13704                         opt_t = optionarg;
13705                         break;
13706                 case 'r':
13707                         read_flags |= BUILTIN_READ_RAW;
13708                         break;
13709                 case 'u':
13710                         opt_u = optionarg;
13711                         break;
13712 #if BASH_READ_D
13713                 case 'd':
13714                         opt_d = optionarg;
13715                         break;
13716 #endif
13717                 default:
13718                         break;
13719                 }
13720         }
13721
13722         /* "read -s" needs to save/restore termios, can't allow ^C
13723          * to jump out of it.
13724          */
13725  again:
13726         INT_OFF;
13727         r = shell_builtin_read(setvar0,
13728                 argptr,
13729                 bltinlookup("IFS"), /* can be NULL */
13730                 read_flags,
13731                 opt_n,
13732                 opt_p,
13733                 opt_t,
13734                 opt_u,
13735                 opt_d
13736         );
13737         INT_ON;
13738
13739         if ((uintptr_t)r == 1 && errno == EINTR) {
13740                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13741                  * Correct behavior is to not exit "read"
13742                  */
13743                 if (pending_sig == 0)
13744                         goto again;
13745         }
13746
13747         if ((uintptr_t)r > 1)
13748                 ash_msg_and_raise_error(r);
13749
13750         return (uintptr_t)r;
13751 }
13752
13753 static int FAST_FUNC
13754 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13755 {
13756         static const char permuser[3] ALIGN1 = "ogu";
13757
13758         mode_t mask;
13759         int symbolic_mode = 0;
13760
13761         while (nextopt("S") != '\0') {
13762                 symbolic_mode = 1;
13763         }
13764
13765         INT_OFF;
13766         mask = umask(0);
13767         umask(mask);
13768         INT_ON;
13769
13770         if (*argptr == NULL) {
13771                 if (symbolic_mode) {
13772                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13773                         char *p = buf;
13774                         int i;
13775
13776                         i = 2;
13777                         for (;;) {
13778                                 *p++ = ',';
13779                                 *p++ = permuser[i];
13780                                 *p++ = '=';
13781                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13782                                 if (!(mask & 0400)) *p++ = 'r';
13783                                 if (!(mask & 0200)) *p++ = 'w';
13784                                 if (!(mask & 0100)) *p++ = 'x';
13785                                 mask <<= 3;
13786                                 if (--i < 0)
13787                                         break;
13788                         }
13789                         *p = '\0';
13790                         puts(buf + 1);
13791                 } else {
13792                         out1fmt("%04o\n", mask);
13793                 }
13794         } else {
13795                 char *modestr = *argptr;
13796                 /* numeric umasks are taken as-is */
13797                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13798                 if (!isdigit(modestr[0]))
13799                         mask ^= 0777;
13800                 mask = bb_parse_mode(modestr, mask);
13801                 if ((unsigned)mask > 0777) {
13802                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13803                 }
13804                 if (!isdigit(modestr[0]))
13805                         mask ^= 0777;
13806                 umask(mask);
13807         }
13808         return 0;
13809 }
13810
13811 static int FAST_FUNC
13812 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13813 {
13814         return shell_builtin_ulimit(argv);
13815 }
13816
13817 /* ============ main() and helpers */
13818
13819 /*
13820  * Called to exit the shell.
13821  */
13822 static void
13823 exitshell(void)
13824 {
13825         struct jmploc loc;
13826         char *p;
13827         int status;
13828
13829 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13830         save_history(line_input_state);
13831 #endif
13832         status = exitstatus;
13833         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13834         if (setjmp(loc.loc)) {
13835                 if (exception_type == EXEXIT)
13836                         status = exitstatus;
13837                 goto out;
13838         }
13839         exception_handler = &loc;
13840         p = trap[0];
13841         if (p) {
13842                 trap[0] = NULL;
13843                 evalskip = 0;
13844                 evalstring(p, 0);
13845                 /*free(p); - we'll exit soon */
13846         }
13847  out:
13848         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13849          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13850          */
13851         setjobctl(0);
13852         flush_stdout_stderr();
13853         _exit(status);
13854         /* NOTREACHED */
13855 }
13856
13857 /* Don't inline: conserve stack of caller from having our locals too */
13858 static NOINLINE void
13859 init(void)
13860 {
13861         /* we will never free this */
13862         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13863         basepf.linno = 1;
13864
13865         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13866         setsignal(SIGCHLD);
13867
13868         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13869          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13870          */
13871         signal(SIGHUP, SIG_DFL);
13872
13873         {
13874                 char **envp;
13875                 const char *p;
13876
13877                 initvar();
13878                 for (envp = environ; envp && *envp; envp++) {
13879 /* Used to have
13880  *                      p = endofname(*envp);
13881  *                      if (p != *envp && *p == '=') {
13882  * here to weed out badly-named variables, but this breaks
13883  * scenarios where people do want them passed to children:
13884  * import os
13885  * os.environ["test-test"]="test"
13886  * if os.fork() == 0:
13887  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13888  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13889  */
13890                         if (strchr(*envp, '=')) {
13891                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13892                         }
13893                 }
13894
13895                 setvareq((char*)defoptindvar, VTEXTFIXED);
13896
13897                 setvar0("PPID", utoa(getppid()));
13898 #if BASH_SHLVL_VAR
13899                 p = lookupvar("SHLVL");
13900                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13901 #endif
13902 #if BASH_HOSTNAME_VAR
13903                 if (!lookupvar("HOSTNAME")) {
13904                         struct utsname uts;
13905                         uname(&uts);
13906                         setvar0("HOSTNAME", uts.nodename);
13907                 }
13908 #endif
13909                 p = lookupvar("PWD");
13910                 if (p) {
13911                         struct stat st1, st2;
13912                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13913                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13914                         ) {
13915                                 p = NULL;
13916                         }
13917                 }
13918                 setpwd(p, 0);
13919         }
13920 }
13921
13922
13923 //usage:#define ash_trivial_usage
13924 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13925 //usage:#define ash_full_usage "\n\n"
13926 //usage:        "Unix shell interpreter"
13927
13928 /*
13929  * Process the shell command line arguments.
13930  */
13931 static int
13932 procargs(char **argv)
13933 {
13934         int i;
13935         const char *xminusc;
13936         char **xargv;
13937         int login_sh;
13938
13939         xargv = argv;
13940         login_sh = xargv[0] && xargv[0][0] == '-';
13941         arg0 = xargv[0];
13942         /* if (xargv[0]) - mmm, this is always true! */
13943                 xargv++;
13944         for (i = 0; i < NOPTS; i++)
13945                 optlist[i] = 2;
13946         argptr = xargv;
13947         if (options(/*cmdline:*/ 1, &login_sh)) {
13948                 /* it already printed err message */
13949                 raise_exception(EXERROR);
13950         }
13951         xargv = argptr;
13952         xminusc = minusc;
13953         if (*xargv == NULL) {
13954                 if (xminusc)
13955                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13956                 sflag = 1;
13957         }
13958         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13959                 iflag = 1;
13960         if (mflag == 2)
13961                 mflag = iflag;
13962         for (i = 0; i < NOPTS; i++)
13963                 if (optlist[i] == 2)
13964                         optlist[i] = 0;
13965 #if DEBUG == 2
13966         debug = 1;
13967 #endif
13968         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13969         if (xminusc) {
13970                 minusc = *xargv++;
13971                 if (*xargv)
13972                         goto setarg0;
13973         } else if (!sflag) {
13974                 setinputfile(*xargv, 0);
13975  setarg0:
13976                 arg0 = *xargv++;
13977                 commandname = arg0;
13978         }
13979
13980         shellparam.p = xargv;
13981 #if ENABLE_ASH_GETOPTS
13982         shellparam.optind = 1;
13983         shellparam.optoff = -1;
13984 #endif
13985         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13986         while (*xargv) {
13987                 shellparam.nparam++;
13988                 xargv++;
13989         }
13990         optschanged();
13991
13992         return login_sh;
13993 }
13994
13995 /*
13996  * Read /etc/profile, ~/.profile, $ENV.
13997  */
13998 static void
13999 read_profile(const char *name)
14000 {
14001         name = expandstr(name, DQSYNTAX);
14002         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14003                 return;
14004         cmdloop(0);
14005         popfile();
14006 }
14007
14008 /*
14009  * This routine is called when an error or an interrupt occurs in an
14010  * interactive shell and control is returned to the main command loop.
14011  * (In dash, this function is auto-generated by build machinery).
14012  */
14013 static void
14014 reset(void)
14015 {
14016         /* from eval.c: */
14017         evalskip = 0;
14018         loopnest = 0;
14019
14020         /* from expand.c: */
14021         ifsfree();
14022
14023         /* from input.c: */
14024         g_parsefile->left_in_buffer = 0;
14025         g_parsefile->left_in_line = 0;      /* clear input buffer */
14026         popallfiles();
14027
14028         /* from redir.c: */
14029         unwindredir(NULL);
14030
14031         /* from var.c: */
14032         unwindlocalvars(NULL);
14033 }
14034
14035 #if PROFILE
14036 static short profile_buf[16384];
14037 extern int etext();
14038 #endif
14039
14040 /*
14041  * Main routine.  We initialize things, parse the arguments, execute
14042  * profiles if we're a login shell, and then call cmdloop to execute
14043  * commands.  The setjmp call sets up the location to jump to when an
14044  * exception occurs.  When an exception occurs the variable "state"
14045  * is used to figure out how far we had gotten.
14046  */
14047 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14048 int ash_main(int argc UNUSED_PARAM, char **argv)
14049 {
14050         volatile smallint state;
14051         struct jmploc jmploc;
14052         struct stackmark smark;
14053         int login_sh;
14054
14055         /* Initialize global data */
14056         INIT_G_misc();
14057         INIT_G_memstack();
14058         INIT_G_var();
14059 #if ENABLE_ASH_ALIAS
14060         INIT_G_alias();
14061 #endif
14062         INIT_G_cmdtable();
14063
14064 #if PROFILE
14065         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14066 #endif
14067
14068 #if ENABLE_FEATURE_EDITING
14069         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14070 #endif
14071         state = 0;
14072         if (setjmp(jmploc.loc)) {
14073                 smallint e;
14074                 smallint s;
14075
14076                 reset();
14077
14078                 e = exception_type;
14079                 s = state;
14080                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14081                         exitshell();
14082                 }
14083                 if (e == EXINT) {
14084                         newline_and_flush(stderr);
14085                 }
14086
14087                 popstackmark(&smark);
14088                 FORCE_INT_ON; /* enable interrupts */
14089                 if (s == 1)
14090                         goto state1;
14091                 if (s == 2)
14092                         goto state2;
14093                 if (s == 3)
14094                         goto state3;
14095                 goto state4;
14096         }
14097         exception_handler = &jmploc;
14098         rootpid = getpid();
14099
14100         init();
14101         setstackmark(&smark);
14102         login_sh = procargs(argv);
14103 #if DEBUG
14104         TRACE(("Shell args: "));
14105         trace_puts_args(argv);
14106 #endif
14107
14108         if (login_sh) {
14109                 const char *hp;
14110
14111                 state = 1;
14112                 read_profile("/etc/profile");
14113  state1:
14114                 state = 2;
14115                 hp = lookupvar("HOME");
14116                 if (hp)
14117                         read_profile("$HOME/.profile");
14118         }
14119  state2:
14120         state = 3;
14121         if (
14122 #ifndef linux
14123          getuid() == geteuid() && getgid() == getegid() &&
14124 #endif
14125          iflag
14126         ) {
14127                 const char *shinit = lookupvar("ENV");
14128                 if (shinit != NULL && *shinit != '\0')
14129                         read_profile(shinit);
14130         }
14131         popstackmark(&smark);
14132  state3:
14133         state = 4;
14134         if (minusc) {
14135                 /* evalstring pushes parsefile stack.
14136                  * Ensure we don't falsely claim that 0 (stdin)
14137                  * is one of stacked source fds.
14138                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14139                 // if (!sflag) g_parsefile->pf_fd = -1;
14140                 // ^^ not necessary since now we special-case fd 0
14141                 // in save_fd_on_redirect()
14142                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14143         }
14144
14145         if (sflag || minusc == NULL) {
14146 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14147                 if (iflag) {
14148                         const char *hp = lookupvar("HISTFILE");
14149                         if (!hp) {
14150                                 hp = lookupvar("HOME");
14151                                 if (hp) {
14152                                         INT_OFF;
14153                                         hp = concat_path_file(hp, ".ash_history");
14154                                         setvar0("HISTFILE", hp);
14155                                         free((char*)hp);
14156                                         INT_ON;
14157                                         hp = lookupvar("HISTFILE");
14158                                 }
14159                         }
14160                         if (hp)
14161                                 line_input_state->hist_file = hp;
14162 # if ENABLE_FEATURE_SH_HISTFILESIZE
14163                         hp = lookupvar("HISTFILESIZE");
14164                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14165 # endif
14166                 }
14167 #endif
14168  state4: /* XXX ??? - why isn't this before the "if" statement */
14169                 cmdloop(1);
14170         }
14171 #if PROFILE
14172         monitor(0);
14173 #endif
14174 #ifdef GPROF
14175         {
14176                 extern void _mcleanup(void);
14177                 _mcleanup();
14178         }
14179 #endif
14180         TRACE(("End of main reached\n"));
14181         exitshell();
14182         /* NOTREACHED */
14183 }
14184
14185
14186 /*-
14187  * Copyright (c) 1989, 1991, 1993, 1994
14188  *      The Regents of the University of California.  All rights reserved.
14189  *
14190  * This code is derived from software contributed to Berkeley by
14191  * Kenneth Almquist.
14192  *
14193  * Redistribution and use in source and binary forms, with or without
14194  * modification, are permitted provided that the following conditions
14195  * are met:
14196  * 1. Redistributions of source code must retain the above copyright
14197  *    notice, this list of conditions and the following disclaimer.
14198  * 2. Redistributions in binary form must reproduce the above copyright
14199  *    notice, this list of conditions and the following disclaimer in the
14200  *    documentation and/or other materials provided with the distribution.
14201  * 3. Neither the name of the University nor the names of its contributors
14202  *    may be used to endorse or promote products derived from this software
14203  *    without specific prior written permission.
14204  *
14205  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14206  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14207  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14208  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14209  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14210  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14211  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14212  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14213  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14214  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14215  * SUCH DAMAGE.
14216  */