5586015439cf5d58030731d43c838702fba74c2a
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_BASH_SOURCE_CURDIR
55 //config:       bool "'source' and '.' builtins search current directory after $PATH"
56 //config:       default n   # do not encourage non-standard behavior
57 //config:       depends on ASH_BASH_COMPAT
58 //config:       help
59 //config:       This is not compliant with standards. Avoid if possible.
60 //config:
61 //config:config ASH_BASH_NOT_FOUND_HOOK
62 //config:       bool "command_not_found_handle hook support"
63 //config:       default y
64 //config:       depends on ASH_BASH_COMPAT
65 //config:       help
66 //config:       Enable support for the 'command_not_found_handle' hook function,
67 //config:       from GNU bash, which allows for alternative command not found
68 //config:       handling.
69 //config:
70 //config:config ASH_JOB_CONTROL
71 //config:       bool "Job control"
72 //config:       default y
73 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
74 //config:
75 //config:config ASH_ALIAS
76 //config:       bool "Alias support"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:
80 //config:config ASH_RANDOM_SUPPORT
81 //config:       bool "Pseudorandom generator and $RANDOM variable"
82 //config:       default y
83 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
84 //config:       help
85 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
86 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
87 //config:       You can reset the generator by using a specified start value.
88 //config:       After "unset RANDOM" the generator will switch off and this
89 //config:       variable will no longer have special treatment.
90 //config:
91 //config:config ASH_EXPAND_PRMT
92 //config:       bool "Expand prompt string"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       $PS# may contain volatile content, such as backquote commands.
97 //config:       This option recreates the prompt string from the environment
98 //config:       variable each time it is displayed.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable $TMOUT"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_MAIL
108 //config:       bool "Check for new mail in interactive shell"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:       help
112 //config:       Enable "check for new mail" function:
113 //config:       if set, $MAIL file and $MAILPATH list of files
114 //config:       are checked for mtime changes, and "you have mail"
115 //config:       message is printed if change is detected.
116 //config:
117 //config:config ASH_ECHO
118 //config:       bool "echo builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_PRINTF
123 //config:       bool "printf builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_TEST
128 //config:       bool "test builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:
132 //config:config ASH_HELP
133 //config:       bool "help builtin"
134 //config:       default y
135 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
136 //config:
137 //config:config ASH_GETOPTS
138 //config:       bool "getopts builtin"
139 //config:       default y
140 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
141 //config:
142 //config:config ASH_CMDCMD
143 //config:       bool "command builtin"
144 //config:       default y
145 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
146 //config:       help
147 //config:       Enable support for the 'command' builtin, which allows
148 //config:       you to run the specified command or builtin,
149 //config:       even when there is a function with the same name.
150 //config:
151 //config:endif # ash options
152
153 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
154 //                      APPLET_ODDNAME:name  main location    suid_type     help
155 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
156 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
157
158 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
159 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
160 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
161 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
162
163 /*
164  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
165  * DEBUG=2 to compile in and turn on debugging.
166  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
167  * debugging info is written to ./trace, quit signal generates core dump.
168  */
169 #define DEBUG 0
170 /* Tweak debug output verbosity here */
171 #define DEBUG_TIME 0
172 #define DEBUG_PID 1
173 #define DEBUG_SIG 1
174 #define DEBUG_INTONOFF 0
175
176 #define PROFILE 0
177
178 #define JOBS ENABLE_ASH_JOB_CONTROL
179
180 #include <setjmp.h>
181 #include <fnmatch.h>
182 #include <sys/times.h>
183 #include <sys/utsname.h> /* for setting $HOSTNAME */
184 #include "busybox.h" /* for applet_names */
185
186 /* So far, all bash compat is controlled by one config option */
187 /* Separate defines document which part of code implements what */
188 /* function keyword */
189 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
190 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
191 /* &>file */
192 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
194 /* $'...' */
195 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
196 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
197 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
198 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
199 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
201 /* [[ EXPR ]] */
202 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
203 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
204 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
205 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
206 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
207 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
208 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
209 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
210
211 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
212 /* Bionic at least up to version 24 has no glob() */
213 # undef  ENABLE_ASH_INTERNAL_GLOB
214 # define ENABLE_ASH_INTERNAL_GLOB 1
215 #endif
216
217 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
218 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
219 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
220 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
221 # error glob() should unbackslash them and match. uClibc does not unbackslash,
222 # error fails to match dirname, subsequently not expanding <pattern> in it.
223 // Testcase:
224 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
225 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
226 #endif
227
228 #if !ENABLE_ASH_INTERNAL_GLOB
229 # include <glob.h>
230 #endif
231
232 #include "unicode.h"
233 #include "shell_common.h"
234 #if ENABLE_FEATURE_SH_MATH
235 # include "math.h"
236 #else
237 typedef long arith_t;
238 # define ARITH_FMT "%ld"
239 #endif
240 #if ENABLE_ASH_RANDOM_SUPPORT
241 # include "random.h"
242 #else
243 # define CLEAR_RANDOM_T(rnd) ((void)0)
244 #endif
245
246 #include "NUM_APPLETS.h"
247 #if NUM_APPLETS == 1
248 /* STANDALONE does not make sense, and won't compile */
249 # undef CONFIG_FEATURE_SH_STANDALONE
250 # undef ENABLE_FEATURE_SH_STANDALONE
251 # undef IF_FEATURE_SH_STANDALONE
252 # undef IF_NOT_FEATURE_SH_STANDALONE
253 # define ENABLE_FEATURE_SH_STANDALONE 0
254 # define IF_FEATURE_SH_STANDALONE(...)
255 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
256 #endif
257
258 #ifndef F_DUPFD_CLOEXEC
259 # define F_DUPFD_CLOEXEC F_DUPFD
260 #endif
261 #ifndef O_CLOEXEC
262 # define O_CLOEXEC 0
263 #endif
264 #ifndef PIPE_BUF
265 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
266 #endif
267
268 #if !BB_MMU
269 # error "Do not even bother, ash will not run on NOMMU machine"
270 #endif
271
272 /* We use a trick to have more optimized code (fewer pointer reloads):
273  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
274  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
275  * This way, compiler in ash.c knows the pointer can not change.
276  *
277  * However, this may break on weird arches or toolchains. In this case,
278  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
279  * this optimization.
280  */
281 #ifndef BB_GLOBAL_CONST
282 # define BB_GLOBAL_CONST const
283 #endif
284
285
286 /* ============ Hash table sizes. Configurable. */
287
288 #define VTABSIZE 39
289 #define ATABSIZE 39
290 #define CMDTABLESIZE 31         /* should be prime */
291
292
293 /* ============ Shell options */
294
295 static const char *const optletters_optnames[] = {
296         "e"   "errexit",
297         "f"   "noglob",
298         "I"   "ignoreeof",
299         "i"   "interactive",
300         "m"   "monitor",
301         "n"   "noexec",
302         "s"   "stdin",
303         "x"   "xtrace",
304         "v"   "verbose",
305         "C"   "noclobber",
306         "a"   "allexport",
307         "b"   "notify",
308         "u"   "nounset",
309         "\0"  "vi"
310 #if BASH_PIPEFAIL
311         ,"\0"  "pipefail"
312 #endif
313 #if DEBUG
314         ,"\0"  "nolog"
315         ,"\0"  "debug"
316 #endif
317 };
318
319 #define optletters(n)  optletters_optnames[n][0]
320 #define optnames(n)   (optletters_optnames[n] + 1)
321
322 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
323
324
325 /* ============ Misc data */
326
327 #define msg_illnum "Illegal number: %s"
328
329 /*
330  * We enclose jmp_buf in a structure so that we can declare pointers to
331  * jump locations.  The global variable handler contains the location to
332  * jump to when an exception occurs, and the global variable exception_type
333  * contains a code identifying the exception.  To implement nested
334  * exception handlers, the user should save the value of handler on entry
335  * to an inner scope, set handler to point to a jmploc structure for the
336  * inner scope, and restore handler on exit from the scope.
337  */
338 struct jmploc {
339         jmp_buf loc;
340 };
341
342 struct globals_misc {
343         uint8_t exitstatus;     /* exit status of last command */
344         uint8_t back_exitstatus;/* exit status of backquoted command */
345         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
346         int rootpid;            /* pid of main shell */
347         /* shell level: 0 for the main shell, 1 for its children, and so on */
348         int shlvl;
349 #define rootshell (!shlvl)
350         int errlinno;
351
352         char *minusc;  /* argument to -c option */
353
354         char *curdir; // = nullstr;     /* current working directory */
355         char *physdir; // = nullstr;    /* physical working directory */
356
357         char *arg0; /* value of $0 */
358
359         struct jmploc *exception_handler;
360
361         volatile int suppress_int; /* counter */
362         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
363         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
364         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
365         smallint exception_type; /* kind of exception (0..5) */
366         /* exceptions */
367 #define EXINT 0         /* SIGINT received */
368 #define EXERROR 1       /* a generic error */
369 #define EXEXIT 4        /* exit the shell */
370
371         char nullstr[1];        /* zero length string */
372
373         char optlist[NOPTS];
374 #define eflag optlist[0]
375 #define fflag optlist[1]
376 #define Iflag optlist[2]
377 #define iflag optlist[3]
378 #define mflag optlist[4]
379 #define nflag optlist[5]
380 #define sflag optlist[6]
381 #define xflag optlist[7]
382 #define vflag optlist[8]
383 #define Cflag optlist[9]
384 #define aflag optlist[10]
385 #define bflag optlist[11]
386 #define uflag optlist[12]
387 #define viflag optlist[13]
388 #if BASH_PIPEFAIL
389 # define pipefail optlist[14]
390 #else
391 # define pipefail 0
392 #endif
393 #if DEBUG
394 # define nolog optlist[14 + BASH_PIPEFAIL]
395 # define debug optlist[15 + BASH_PIPEFAIL]
396 #endif
397
398         /* trap handler commands */
399         /*
400          * Sigmode records the current value of the signal handlers for the various
401          * modes.  A value of zero means that the current handler is not known.
402          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
403          */
404         char sigmode[NSIG - 1];
405 #define S_DFL      1            /* default signal handling (SIG_DFL) */
406 #define S_CATCH    2            /* signal is caught */
407 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
408 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
409
410         /* indicates specified signal received */
411         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
412         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
413         char *trap[NSIG];
414         char **trap_ptr;        /* used only by "trap hack" */
415
416         /* Rarely referenced stuff */
417 #if ENABLE_ASH_RANDOM_SUPPORT
418         random_t random_gen;
419 #endif
420         pid_t backgndpid;        /* pid of last background process */
421 };
422 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
423 #define G_misc (*ash_ptr_to_globals_misc)
424 #define exitstatus        (G_misc.exitstatus )
425 #define back_exitstatus   (G_misc.back_exitstatus )
426 #define job_warning       (G_misc.job_warning)
427 #define rootpid     (G_misc.rootpid    )
428 #define shlvl       (G_misc.shlvl      )
429 #define errlinno    (G_misc.errlinno   )
430 #define minusc      (G_misc.minusc     )
431 #define curdir      (G_misc.curdir     )
432 #define physdir     (G_misc.physdir    )
433 #define arg0        (G_misc.arg0       )
434 #define exception_handler (G_misc.exception_handler)
435 #define exception_type    (G_misc.exception_type   )
436 #define suppress_int      (G_misc.suppress_int     )
437 #define pending_int       (G_misc.pending_int      )
438 #define got_sigchld       (G_misc.got_sigchld      )
439 #define pending_sig       (G_misc.pending_sig      )
440 #define nullstr     (G_misc.nullstr    )
441 #define optlist     (G_misc.optlist    )
442 #define sigmode     (G_misc.sigmode    )
443 #define gotsig      (G_misc.gotsig     )
444 #define may_have_traps    (G_misc.may_have_traps   )
445 #define trap        (G_misc.trap       )
446 #define trap_ptr    (G_misc.trap_ptr   )
447 #define random_gen  (G_misc.random_gen )
448 #define backgndpid  (G_misc.backgndpid )
449 #define INIT_G_misc() do { \
450         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
451         barrier(); \
452         curdir = nullstr; \
453         physdir = nullstr; \
454         trap_ptr = trap; \
455 } while (0)
456
457
458 /* ============ DEBUG */
459 #if DEBUG
460 static void trace_printf(const char *fmt, ...);
461 static void trace_vprintf(const char *fmt, va_list va);
462 # define TRACE(param)    trace_printf param
463 # define TRACEV(param)   trace_vprintf param
464 # define close(fd) do { \
465         int dfd = (fd); \
466         if (close(dfd) < 0) \
467                 bb_error_msg("bug on %d: closing %d(0x%x)", \
468                         __LINE__, dfd, dfd); \
469 } while (0)
470 #else
471 # define TRACE(param)
472 # define TRACEV(param)
473 #endif
474
475
476 /* ============ Utility functions */
477 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
478 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
479
480 static int
481 isdigit_str9(const char *str)
482 {
483         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
484         while (--maxlen && isdigit(*str))
485                 str++;
486         return (*str == '\0');
487 }
488
489 static const char *
490 var_end(const char *var)
491 {
492         while (*var)
493                 if (*var++ == '=')
494                         break;
495         return var;
496 }
497
498
499 /* ============ Interrupts / exceptions */
500
501 static void exitshell(void) NORETURN;
502
503 /*
504  * These macros allow the user to suspend the handling of interrupt signals
505  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
506  * much more efficient and portable.  (But hacking the kernel is so much
507  * more fun than worrying about efficiency and portability. :-))
508  */
509 #if DEBUG_INTONOFF
510 # define INT_OFF do { \
511         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
512         suppress_int++; \
513         barrier(); \
514 } while (0)
515 #else
516 # define INT_OFF do { \
517         suppress_int++; \
518         barrier(); \
519 } while (0)
520 #endif
521
522 /*
523  * Called to raise an exception.  Since C doesn't include exceptions, we
524  * just do a longjmp to the exception handler.  The type of exception is
525  * stored in the global variable "exception_type".
526  */
527 static void raise_exception(int) NORETURN;
528 static void
529 raise_exception(int e)
530 {
531 #if DEBUG
532         if (exception_handler == NULL)
533                 abort();
534 #endif
535         INT_OFF;
536         exception_type = e;
537         longjmp(exception_handler->loc, 1);
538 }
539 #if DEBUG
540 #define raise_exception(e) do { \
541         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
542         raise_exception(e); \
543 } while (0)
544 #endif
545
546 /*
547  * Called when a SIGINT is received.  (If the user specifies
548  * that SIGINT is to be trapped or ignored using the trap builtin, then
549  * this routine is not called.)  Suppressint is nonzero when interrupts
550  * are held using the INT_OFF macro.  (The test for iflag is just
551  * defensive programming.)
552  */
553 static void raise_interrupt(void) NORETURN;
554 static void
555 raise_interrupt(void)
556 {
557         pending_int = 0;
558         /* Signal is not automatically unmasked after it is raised,
559          * do it ourself - unmask all signals */
560         sigprocmask_allsigs(SIG_UNBLOCK);
561         /* pending_sig = 0; - now done in signal_handler() */
562
563         if (!(rootshell && iflag)) {
564                 /* Kill ourself with SIGINT */
565                 signal(SIGINT, SIG_DFL);
566                 raise(SIGINT);
567         }
568         /* bash: ^C even on empty command line sets $? */
569         exitstatus = SIGINT + 128;
570         raise_exception(EXINT);
571         /* NOTREACHED */
572 }
573 #if DEBUG
574 #define raise_interrupt() do { \
575         TRACE(("raising interrupt on line %d\n", __LINE__)); \
576         raise_interrupt(); \
577 } while (0)
578 #endif
579
580 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
581 int_on(void)
582 {
583         barrier();
584         if (--suppress_int == 0 && pending_int) {
585                 raise_interrupt();
586         }
587 }
588 #if DEBUG_INTONOFF
589 # define INT_ON do { \
590         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
591         int_on(); \
592 } while (0)
593 #else
594 # define INT_ON int_on()
595 #endif
596 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
597 force_int_on(void)
598 {
599         barrier();
600         suppress_int = 0;
601         if (pending_int)
602                 raise_interrupt();
603 }
604 #define FORCE_INT_ON force_int_on()
605
606 #define SAVE_INT(v) ((v) = suppress_int)
607
608 #define RESTORE_INT(v) do { \
609         barrier(); \
610         suppress_int = (v); \
611         if (suppress_int == 0 && pending_int) \
612                 raise_interrupt(); \
613 } while (0)
614
615
616 /* ============ Stdout/stderr output */
617
618 static void
619 outstr(const char *p, FILE *file)
620 {
621         INT_OFF;
622         fputs(p, file);
623         INT_ON;
624 }
625
626 static void
627 flush_stdout_stderr(void)
628 {
629         INT_OFF;
630         fflush_all();
631         INT_ON;
632 }
633
634 /* Was called outcslow(c,FILE*), but c was always '\n' */
635 static void
636 newline_and_flush(FILE *dest)
637 {
638         INT_OFF;
639         putc('\n', dest);
640         fflush(dest);
641         INT_ON;
642 }
643
644 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
645 static int
646 out1fmt(const char *fmt, ...)
647 {
648         va_list ap;
649         int r;
650
651         INT_OFF;
652         va_start(ap, fmt);
653         r = vprintf(fmt, ap);
654         va_end(ap);
655         INT_ON;
656         return r;
657 }
658
659 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
660 static int
661 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
662 {
663         va_list ap;
664         int ret;
665
666         INT_OFF;
667         va_start(ap, fmt);
668         ret = vsnprintf(outbuf, length, fmt, ap);
669         va_end(ap);
670         INT_ON;
671         return ret;
672 }
673
674 static void
675 out1str(const char *p)
676 {
677         outstr(p, stdout);
678 }
679
680 static void
681 out2str(const char *p)
682 {
683         outstr(p, stderr);
684         flush_stdout_stderr();
685 }
686
687
688 /* ============ Parser structures */
689
690 /* control characters in argument strings */
691 #define CTL_FIRST CTLESC
692 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
693 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
694 #define CTLENDVAR    ((unsigned char)'\203')
695 #define CTLBACKQ     ((unsigned char)'\204')
696 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
697 #define CTLENDARI    ((unsigned char)'\207')
698 #define CTLQUOTEMARK ((unsigned char)'\210')
699 #define CTL_LAST CTLQUOTEMARK
700
701 /* variable substitution byte (follows CTLVAR) */
702 #define VSTYPE  0x0f            /* type of variable substitution */
703 #define VSNUL   0x10            /* colon--treat the empty string as unset */
704
705 /* values of VSTYPE field */
706 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
707 #define VSMINUS         0x2     /* ${var-text} */
708 #define VSPLUS          0x3     /* ${var+text} */
709 #define VSQUESTION      0x4     /* ${var?message} */
710 #define VSASSIGN        0x5     /* ${var=text} */
711 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
712 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
713 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
714 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
715 #define VSLENGTH        0xa     /* ${#var} */
716 #if BASH_SUBSTR
717 #define VSSUBSTR        0xc     /* ${var:position:length} */
718 #endif
719 #if BASH_PATTERN_SUBST
720 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
721 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
722 #endif
723
724 static const char dolatstr[] ALIGN1 = {
725         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
726 };
727 #define DOLATSTRLEN 6
728
729 #define NCMD      0
730 #define NPIPE     1
731 #define NREDIR    2
732 #define NBACKGND  3
733 #define NSUBSHELL 4
734 #define NAND      5
735 #define NOR       6
736 #define NSEMI     7
737 #define NIF       8
738 #define NWHILE    9
739 #define NUNTIL   10
740 #define NFOR     11
741 #define NCASE    12
742 #define NCLIST   13
743 #define NDEFUN   14
744 #define NARG     15
745 #define NTO      16
746 #if BASH_REDIR_OUTPUT
747 #define NTO2     17
748 #endif
749 #define NCLOBBER 18
750 #define NFROM    19
751 #define NFROMTO  20
752 #define NAPPEND  21
753 #define NTOFD    22
754 #define NFROMFD  23
755 #define NHERE    24
756 #define NXHERE   25
757 #define NNOT     26
758 #define N_NUMBER 27
759
760 union node;
761
762 struct ncmd {
763         smallint type; /* Nxxxx */
764         int linno;
765         union node *assign;
766         union node *args;
767         union node *redirect;
768 };
769
770 struct npipe {
771         smallint type;
772         smallint pipe_backgnd;
773         struct nodelist *cmdlist;
774 };
775
776 struct nredir {
777         smallint type;
778         int linno;
779         union node *n;
780         union node *redirect;
781 };
782
783 struct nbinary {
784         smallint type;
785         union node *ch1;
786         union node *ch2;
787 };
788
789 struct nif {
790         smallint type;
791         union node *test;
792         union node *ifpart;
793         union node *elsepart;
794 };
795
796 struct nfor {
797         smallint type;
798         int linno;
799         union node *args;
800         union node *body;
801         char *var;
802 };
803
804 struct ncase {
805         smallint type;
806         int linno;
807         union node *expr;
808         union node *cases;
809 };
810
811 struct nclist {
812         smallint type;
813         union node *next;
814         union node *pattern;
815         union node *body;
816 };
817
818 struct ndefun {
819         smallint type;
820         int linno;
821         char *text;
822         union node *body;
823 };
824
825 struct narg {
826         smallint type;
827         union node *next;
828         char *text;
829         struct nodelist *backquote;
830 };
831
832 /* nfile and ndup layout must match!
833  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
834  * that it is actually NTO2 (>&file), and change its type.
835  */
836 struct nfile {
837         smallint type;
838         union node *next;
839         int fd;
840         int _unused_dupfd;
841         union node *fname;
842         char *expfname;
843 };
844
845 struct ndup {
846         smallint type;
847         union node *next;
848         int fd;
849         int dupfd;
850         union node *vname;
851         char *_unused_expfname;
852 };
853
854 struct nhere {
855         smallint type;
856         union node *next;
857         int fd;
858         union node *doc;
859 };
860
861 struct nnot {
862         smallint type;
863         union node *com;
864 };
865
866 union node {
867         smallint type;
868         struct ncmd ncmd;
869         struct npipe npipe;
870         struct nredir nredir;
871         struct nbinary nbinary;
872         struct nif nif;
873         struct nfor nfor;
874         struct ncase ncase;
875         struct nclist nclist;
876         struct ndefun ndefun;
877         struct narg narg;
878         struct nfile nfile;
879         struct ndup ndup;
880         struct nhere nhere;
881         struct nnot nnot;
882 };
883
884 /*
885  * NODE_EOF is returned by parsecmd when it encounters an end of file.
886  * It must be distinct from NULL.
887  */
888 #define NODE_EOF ((union node *) -1L)
889
890 struct nodelist {
891         struct nodelist *next;
892         union node *n;
893 };
894
895 struct funcnode {
896         int count;
897         union node n;
898 };
899
900 /*
901  * Free a parse tree.
902  */
903 static void
904 freefunc(struct funcnode *f)
905 {
906         if (f && --f->count < 0)
907                 free(f);
908 }
909
910
911 /* ============ Debugging output */
912
913 #if DEBUG
914
915 static FILE *tracefile;
916
917 static void
918 trace_printf(const char *fmt, ...)
919 {
920         va_list va;
921
922         if (debug != 1)
923                 return;
924         if (DEBUG_TIME)
925                 fprintf(tracefile, "%u ", (int) time(NULL));
926         if (DEBUG_PID)
927                 fprintf(tracefile, "[%u] ", (int) getpid());
928         if (DEBUG_SIG)
929                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
930         va_start(va, fmt);
931         vfprintf(tracefile, fmt, va);
932         va_end(va);
933 }
934
935 static void
936 trace_vprintf(const char *fmt, va_list va)
937 {
938         if (debug != 1)
939                 return;
940         vfprintf(tracefile, fmt, va);
941         fprintf(tracefile, "\n");
942 }
943
944 static void
945 trace_puts(const char *s)
946 {
947         if (debug != 1)
948                 return;
949         fputs(s, tracefile);
950 }
951
952 static void
953 trace_puts_quoted(char *s)
954 {
955         char *p;
956         char c;
957
958         if (debug != 1)
959                 return;
960         putc('"', tracefile);
961         for (p = s; *p; p++) {
962                 switch ((unsigned char)*p) {
963                 case '\n': c = 'n'; goto backslash;
964                 case '\t': c = 't'; goto backslash;
965                 case '\r': c = 'r'; goto backslash;
966                 case '\"': c = '\"'; goto backslash;
967                 case '\\': c = '\\'; goto backslash;
968                 case CTLESC: c = 'e'; goto backslash;
969                 case CTLVAR: c = 'v'; goto backslash;
970                 case CTLBACKQ: c = 'q'; goto backslash;
971  backslash:
972                         putc('\\', tracefile);
973                         putc(c, tracefile);
974                         break;
975                 default:
976                         if (*p >= ' ' && *p <= '~')
977                                 putc(*p, tracefile);
978                         else {
979                                 putc('\\', tracefile);
980                                 putc((*p >> 6) & 03, tracefile);
981                                 putc((*p >> 3) & 07, tracefile);
982                                 putc(*p & 07, tracefile);
983                         }
984                         break;
985                 }
986         }
987         putc('"', tracefile);
988 }
989
990 static void
991 trace_puts_args(char **ap)
992 {
993         if (debug != 1)
994                 return;
995         if (!*ap)
996                 return;
997         while (1) {
998                 trace_puts_quoted(*ap);
999                 if (!*++ap) {
1000                         putc('\n', tracefile);
1001                         break;
1002                 }
1003                 putc(' ', tracefile);
1004         }
1005 }
1006
1007 static void
1008 opentrace(void)
1009 {
1010         char s[100];
1011 #ifdef O_APPEND
1012         int flags;
1013 #endif
1014
1015         if (debug != 1) {
1016                 if (tracefile)
1017                         fflush(tracefile);
1018                 /* leave open because libedit might be using it */
1019                 return;
1020         }
1021         strcpy(s, "./trace");
1022         if (tracefile) {
1023                 if (!freopen(s, "a", tracefile)) {
1024                         fprintf(stderr, "Can't re-open %s\n", s);
1025                         debug = 0;
1026                         return;
1027                 }
1028         } else {
1029                 tracefile = fopen(s, "a");
1030                 if (tracefile == NULL) {
1031                         fprintf(stderr, "Can't open %s\n", s);
1032                         debug = 0;
1033                         return;
1034                 }
1035         }
1036 #ifdef O_APPEND
1037         flags = fcntl(fileno(tracefile), F_GETFL);
1038         if (flags >= 0)
1039                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1040 #endif
1041         setlinebuf(tracefile);
1042         fputs("\nTracing started.\n", tracefile);
1043 }
1044
1045 static void
1046 indent(int amount, char *pfx, FILE *fp)
1047 {
1048         int i;
1049
1050         for (i = 0; i < amount; i++) {
1051                 if (pfx && i == amount - 1)
1052                         fputs(pfx, fp);
1053                 putc('\t', fp);
1054         }
1055 }
1056
1057 /* little circular references here... */
1058 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1059
1060 static void
1061 sharg(union node *arg, FILE *fp)
1062 {
1063         char *p;
1064         struct nodelist *bqlist;
1065         unsigned char subtype;
1066
1067         if (arg->type != NARG) {
1068                 out1fmt("<node type %d>\n", arg->type);
1069                 abort();
1070         }
1071         bqlist = arg->narg.backquote;
1072         for (p = arg->narg.text; *p; p++) {
1073                 switch ((unsigned char)*p) {
1074                 case CTLESC:
1075                         p++;
1076                         putc(*p, fp);
1077                         break;
1078                 case CTLVAR:
1079                         putc('$', fp);
1080                         putc('{', fp);
1081                         subtype = *++p;
1082                         if (subtype == VSLENGTH)
1083                                 putc('#', fp);
1084
1085                         while (*p != '=') {
1086                                 putc(*p, fp);
1087                                 p++;
1088                         }
1089
1090                         if (subtype & VSNUL)
1091                                 putc(':', fp);
1092
1093                         switch (subtype & VSTYPE) {
1094                         case VSNORMAL:
1095                                 putc('}', fp);
1096                                 break;
1097                         case VSMINUS:
1098                                 putc('-', fp);
1099                                 break;
1100                         case VSPLUS:
1101                                 putc('+', fp);
1102                                 break;
1103                         case VSQUESTION:
1104                                 putc('?', fp);
1105                                 break;
1106                         case VSASSIGN:
1107                                 putc('=', fp);
1108                                 break;
1109                         case VSTRIMLEFT:
1110                                 putc('#', fp);
1111                                 break;
1112                         case VSTRIMLEFTMAX:
1113                                 putc('#', fp);
1114                                 putc('#', fp);
1115                                 break;
1116                         case VSTRIMRIGHT:
1117                                 putc('%', fp);
1118                                 break;
1119                         case VSTRIMRIGHTMAX:
1120                                 putc('%', fp);
1121                                 putc('%', fp);
1122                                 break;
1123                         case VSLENGTH:
1124                                 break;
1125                         default:
1126                                 out1fmt("<subtype %d>", subtype);
1127                         }
1128                         break;
1129                 case CTLENDVAR:
1130                         putc('}', fp);
1131                         break;
1132                 case CTLBACKQ:
1133                         putc('$', fp);
1134                         putc('(', fp);
1135                         shtree(bqlist->n, -1, NULL, fp);
1136                         putc(')', fp);
1137                         break;
1138                 default:
1139                         putc(*p, fp);
1140                         break;
1141                 }
1142         }
1143 }
1144
1145 static void
1146 shcmd(union node *cmd, FILE *fp)
1147 {
1148         union node *np;
1149         int first;
1150         const char *s;
1151         int dftfd;
1152
1153         first = 1;
1154         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1155                 if (!first)
1156                         putc(' ', fp);
1157                 sharg(np, fp);
1158                 first = 0;
1159         }
1160         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1161                 if (!first)
1162                         putc(' ', fp);
1163                 dftfd = 0;
1164                 switch (np->nfile.type) {
1165                 case NTO:      s = ">>"+1; dftfd = 1; break;
1166                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1167                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1168 #if BASH_REDIR_OUTPUT
1169                 case NTO2:
1170 #endif
1171                 case NTOFD:    s = ">&"; dftfd = 1; break;
1172                 case NFROM:    s = "<"; break;
1173                 case NFROMFD:  s = "<&"; break;
1174                 case NFROMTO:  s = "<>"; break;
1175                 default:       s = "*error*"; break;
1176                 }
1177                 if (np->nfile.fd != dftfd)
1178                         fprintf(fp, "%d", np->nfile.fd);
1179                 fputs(s, fp);
1180                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1181                         fprintf(fp, "%d", np->ndup.dupfd);
1182                 } else {
1183                         sharg(np->nfile.fname, fp);
1184                 }
1185                 first = 0;
1186         }
1187 }
1188
1189 static void
1190 shtree(union node *n, int ind, char *pfx, FILE *fp)
1191 {
1192         struct nodelist *lp;
1193         const char *s;
1194
1195         if (n == NULL)
1196                 return;
1197
1198         indent(ind, pfx, fp);
1199
1200         if (n == NODE_EOF) {
1201                 fputs("<EOF>", fp);
1202                 return;
1203         }
1204
1205         switch (n->type) {
1206         case NSEMI:
1207                 s = "; ";
1208                 goto binop;
1209         case NAND:
1210                 s = " && ";
1211                 goto binop;
1212         case NOR:
1213                 s = " || ";
1214  binop:
1215                 shtree(n->nbinary.ch1, ind, NULL, fp);
1216                 /* if (ind < 0) */
1217                         fputs(s, fp);
1218                 shtree(n->nbinary.ch2, ind, NULL, fp);
1219                 break;
1220         case NCMD:
1221                 shcmd(n, fp);
1222                 if (ind >= 0)
1223                         putc('\n', fp);
1224                 break;
1225         case NPIPE:
1226                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1227                         shtree(lp->n, 0, NULL, fp);
1228                         if (lp->next)
1229                                 fputs(" | ", fp);
1230                 }
1231                 if (n->npipe.pipe_backgnd)
1232                         fputs(" &", fp);
1233                 if (ind >= 0)
1234                         putc('\n', fp);
1235                 break;
1236         default:
1237                 fprintf(fp, "<node type %d>", n->type);
1238                 if (ind >= 0)
1239                         putc('\n', fp);
1240                 break;
1241         }
1242 }
1243
1244 static void
1245 showtree(union node *n)
1246 {
1247         trace_puts("showtree called\n");
1248         shtree(n, 1, NULL, stderr);
1249 }
1250
1251 #endif /* DEBUG */
1252
1253
1254 /* ============ Parser data */
1255
1256 /*
1257  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1258  */
1259 struct strlist {
1260         struct strlist *next;
1261         char *text;
1262 };
1263
1264 struct alias;
1265
1266 struct strpush {
1267         struct strpush *prev;   /* preceding string on stack */
1268         char *prev_string;
1269         int prev_left_in_line;
1270 #if ENABLE_ASH_ALIAS
1271         struct alias *ap;       /* if push was associated with an alias */
1272 #endif
1273         char *string;           /* remember the string since it may change */
1274
1275         /* Remember last two characters for pungetc. */
1276         int lastc[2];
1277
1278         /* Number of outstanding calls to pungetc. */
1279         int unget;
1280 };
1281
1282 /*
1283  * The parsefile structure pointed to by the global variable parsefile
1284  * contains information about the current file being read.
1285  */
1286 struct parsefile {
1287         struct parsefile *prev; /* preceding file on stack */
1288         int linno;              /* current line */
1289         int pf_fd;              /* file descriptor (or -1 if string) */
1290         int left_in_line;       /* number of chars left in this line */
1291         int left_in_buffer;     /* number of chars left in this buffer past the line */
1292         char *next_to_pgetc;    /* next char in buffer */
1293         char *buf;              /* input buffer */
1294         struct strpush *strpush; /* for pushing strings at this level */
1295         struct strpush basestrpush; /* so pushing one is fast */
1296
1297         /* Remember last two characters for pungetc. */
1298         int lastc[2];
1299
1300         /* Number of outstanding calls to pungetc. */
1301         int unget;
1302 };
1303
1304 static struct parsefile basepf;        /* top level input file */
1305 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1306 static char *commandname;              /* currently executing command */
1307
1308
1309 /* ============ Message printing */
1310
1311 static void
1312 ash_vmsg(const char *msg, va_list ap)
1313 {
1314         fprintf(stderr, "%s: ", arg0);
1315         if (commandname) {
1316                 if (strcmp(arg0, commandname))
1317                         fprintf(stderr, "%s: ", commandname);
1318                 if (!iflag || g_parsefile->pf_fd > 0)
1319                         fprintf(stderr, "line %d: ", errlinno);
1320         }
1321         vfprintf(stderr, msg, ap);
1322         newline_and_flush(stderr);
1323 }
1324
1325 /*
1326  * Exverror is called to raise the error exception.  If the second argument
1327  * is not NULL then error prints an error message using printf style
1328  * formatting.  It then raises the error exception.
1329  */
1330 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1331 static void
1332 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1333 {
1334 #if DEBUG
1335         if (msg) {
1336                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1337                 TRACEV((msg, ap));
1338         } else
1339                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1340         if (msg)
1341 #endif
1342                 ash_vmsg(msg, ap);
1343
1344         flush_stdout_stderr();
1345         raise_exception(cond);
1346         /* NOTREACHED */
1347 }
1348
1349 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1350 static void
1351 ash_msg_and_raise_error(const char *msg, ...)
1352 {
1353         va_list ap;
1354
1355         exitstatus = 2;
1356
1357         va_start(ap, msg);
1358         ash_vmsg_and_raise(EXERROR, msg, ap);
1359         /* NOTREACHED */
1360         va_end(ap);
1361 }
1362
1363 /*
1364  * 'fmt' must be a string literal.
1365  */
1366 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1367
1368 static void raise_error_syntax(const char *) NORETURN;
1369 static void
1370 raise_error_syntax(const char *msg)
1371 {
1372         errlinno = g_parsefile->linno;
1373         ash_msg_and_raise_error("syntax error: %s", msg);
1374         /* NOTREACHED */
1375 }
1376
1377 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1378 static void
1379 ash_msg_and_raise(int cond, const char *msg, ...)
1380 {
1381         va_list ap;
1382
1383         va_start(ap, msg);
1384         ash_vmsg_and_raise(cond, msg, ap);
1385         /* NOTREACHED */
1386         va_end(ap);
1387 }
1388
1389 /*
1390  * error/warning routines for external builtins
1391  */
1392 static void
1393 ash_msg(const char *fmt, ...)
1394 {
1395         va_list ap;
1396
1397         va_start(ap, fmt);
1398         ash_vmsg(fmt, ap);
1399         va_end(ap);
1400 }
1401
1402 /*
1403  * Return a string describing an error.  The returned string may be a
1404  * pointer to a static buffer that will be overwritten on the next call.
1405  * Action describes the operation that got the error.
1406  */
1407 static const char *
1408 errmsg(int e, const char *em)
1409 {
1410         if (e == ENOENT || e == ENOTDIR) {
1411                 return em;
1412         }
1413         return strerror(e);
1414 }
1415
1416
1417 /* ============ Memory allocation */
1418
1419 #if 0
1420 /* I consider these wrappers nearly useless:
1421  * ok, they return you to nearest exception handler, but
1422  * how much memory do you leak in the process, making
1423  * memory starvation worse?
1424  */
1425 static void *
1426 ckrealloc(void * p, size_t nbytes)
1427 {
1428         p = realloc(p, nbytes);
1429         if (!p)
1430                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1431         return p;
1432 }
1433
1434 static void *
1435 ckmalloc(size_t nbytes)
1436 {
1437         return ckrealloc(NULL, nbytes);
1438 }
1439
1440 static void *
1441 ckzalloc(size_t nbytes)
1442 {
1443         return memset(ckmalloc(nbytes), 0, nbytes);
1444 }
1445
1446 static char *
1447 ckstrdup(const char *s)
1448 {
1449         char *p = strdup(s);
1450         if (!p)
1451                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1452         return p;
1453 }
1454 #else
1455 /* Using bbox equivalents. They exit if out of memory */
1456 # define ckrealloc xrealloc
1457 # define ckmalloc  xmalloc
1458 # define ckzalloc  xzalloc
1459 # define ckstrdup  xstrdup
1460 #endif
1461
1462 /*
1463  * It appears that grabstackstr() will barf with such alignments
1464  * because stalloc() will return a string allocated in a new stackblock.
1465  */
1466 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1467 enum {
1468         /* Most machines require the value returned from malloc to be aligned
1469          * in some way.  The following macro will get this right
1470          * on many machines.  */
1471         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1472         /* Minimum size of a block */
1473         MINSIZE = SHELL_ALIGN(504),
1474 };
1475
1476 struct stack_block {
1477         struct stack_block *prev;
1478         char space[MINSIZE];
1479 };
1480
1481 struct stackmark {
1482         struct stack_block *stackp;
1483         char *stacknxt;
1484         size_t stacknleft;
1485 };
1486
1487
1488 struct globals_memstack {
1489         struct stack_block *g_stackp; // = &stackbase;
1490         char *g_stacknxt; // = stackbase.space;
1491         char *sstrend; // = stackbase.space + MINSIZE;
1492         size_t g_stacknleft; // = MINSIZE;
1493         struct stack_block stackbase;
1494 };
1495 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1496 #define G_memstack (*ash_ptr_to_globals_memstack)
1497 #define g_stackp     (G_memstack.g_stackp    )
1498 #define g_stacknxt   (G_memstack.g_stacknxt  )
1499 #define sstrend      (G_memstack.sstrend     )
1500 #define g_stacknleft (G_memstack.g_stacknleft)
1501 #define stackbase    (G_memstack.stackbase   )
1502 #define INIT_G_memstack() do { \
1503         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1504         barrier(); \
1505         g_stackp = &stackbase; \
1506         g_stacknxt = stackbase.space; \
1507         g_stacknleft = MINSIZE; \
1508         sstrend = stackbase.space + MINSIZE; \
1509 } while (0)
1510
1511
1512 #define stackblock()     ((void *)g_stacknxt)
1513 #define stackblocksize() g_stacknleft
1514
1515 /*
1516  * Parse trees for commands are allocated in lifo order, so we use a stack
1517  * to make this more efficient, and also to avoid all sorts of exception
1518  * handling code to handle interrupts in the middle of a parse.
1519  *
1520  * The size 504 was chosen because the Ultrix malloc handles that size
1521  * well.
1522  */
1523 static void *
1524 stalloc(size_t nbytes)
1525 {
1526         char *p;
1527         size_t aligned;
1528
1529         aligned = SHELL_ALIGN(nbytes);
1530         if (aligned > g_stacknleft) {
1531                 size_t len;
1532                 size_t blocksize;
1533                 struct stack_block *sp;
1534
1535                 blocksize = aligned;
1536                 if (blocksize < MINSIZE)
1537                         blocksize = MINSIZE;
1538                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1539                 if (len < blocksize)
1540                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1541                 INT_OFF;
1542                 sp = ckmalloc(len);
1543                 sp->prev = g_stackp;
1544                 g_stacknxt = sp->space;
1545                 g_stacknleft = blocksize;
1546                 sstrend = g_stacknxt + blocksize;
1547                 g_stackp = sp;
1548                 INT_ON;
1549         }
1550         p = g_stacknxt;
1551         g_stacknxt += aligned;
1552         g_stacknleft -= aligned;
1553         return p;
1554 }
1555
1556 static void *
1557 stzalloc(size_t nbytes)
1558 {
1559         return memset(stalloc(nbytes), 0, nbytes);
1560 }
1561
1562 static void
1563 stunalloc(void *p)
1564 {
1565 #if DEBUG
1566         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1567                 write(STDERR_FILENO, "stunalloc\n", 10);
1568                 abort();
1569         }
1570 #endif
1571         g_stacknleft += g_stacknxt - (char *)p;
1572         g_stacknxt = p;
1573 }
1574
1575 /*
1576  * Like strdup but works with the ash stack.
1577  */
1578 static char *
1579 sstrdup(const char *p)
1580 {
1581         size_t len = strlen(p) + 1;
1582         return memcpy(stalloc(len), p, len);
1583 }
1584
1585 static ALWAYS_INLINE void
1586 grabstackblock(size_t len)
1587 {
1588         stalloc(len);
1589 }
1590
1591 static void
1592 pushstackmark(struct stackmark *mark, size_t len)
1593 {
1594         mark->stackp = g_stackp;
1595         mark->stacknxt = g_stacknxt;
1596         mark->stacknleft = g_stacknleft;
1597         grabstackblock(len);
1598 }
1599
1600 static void
1601 setstackmark(struct stackmark *mark)
1602 {
1603         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1604 }
1605
1606 static void
1607 popstackmark(struct stackmark *mark)
1608 {
1609         struct stack_block *sp;
1610
1611         if (!mark->stackp)
1612                 return;
1613
1614         INT_OFF;
1615         while (g_stackp != mark->stackp) {
1616                 sp = g_stackp;
1617                 g_stackp = sp->prev;
1618                 free(sp);
1619         }
1620         g_stacknxt = mark->stacknxt;
1621         g_stacknleft = mark->stacknleft;
1622         sstrend = mark->stacknxt + mark->stacknleft;
1623         INT_ON;
1624 }
1625
1626 /*
1627  * When the parser reads in a string, it wants to stick the string on the
1628  * stack and only adjust the stack pointer when it knows how big the
1629  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1630  * of space on top of the stack and stackblocklen returns the length of
1631  * this block.  Growstackblock will grow this space by at least one byte,
1632  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1633  * part of the block that has been used.
1634  */
1635 static void
1636 growstackblock(void)
1637 {
1638         size_t newlen;
1639
1640         newlen = g_stacknleft * 2;
1641         if (newlen < g_stacknleft)
1642                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1643         if (newlen < 128)
1644                 newlen += 128;
1645
1646         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1647                 struct stack_block *sp;
1648                 struct stack_block *prevstackp;
1649                 size_t grosslen;
1650
1651                 INT_OFF;
1652                 sp = g_stackp;
1653                 prevstackp = sp->prev;
1654                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1655                 sp = ckrealloc(sp, grosslen);
1656                 sp->prev = prevstackp;
1657                 g_stackp = sp;
1658                 g_stacknxt = sp->space;
1659                 g_stacknleft = newlen;
1660                 sstrend = sp->space + newlen;
1661                 INT_ON;
1662         } else {
1663                 char *oldspace = g_stacknxt;
1664                 size_t oldlen = g_stacknleft;
1665                 char *p = stalloc(newlen);
1666
1667                 /* free the space we just allocated */
1668                 g_stacknxt = memcpy(p, oldspace, oldlen);
1669                 g_stacknleft += newlen;
1670         }
1671 }
1672
1673 /*
1674  * The following routines are somewhat easier to use than the above.
1675  * The user declares a variable of type STACKSTR, which may be declared
1676  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1677  * the user uses the macro STPUTC to add characters to the string.  In
1678  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1679  * grown as necessary.  When the user is done, she can just leave the
1680  * string there and refer to it using stackblock().  Or she can allocate
1681  * the space for it using grabstackstr().  If it is necessary to allow
1682  * someone else to use the stack temporarily and then continue to grow
1683  * the string, the user should use grabstack to allocate the space, and
1684  * then call ungrabstr(p) to return to the previous mode of operation.
1685  *
1686  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1687  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1688  * is space for at least one character.
1689  */
1690 static void *
1691 growstackstr(void)
1692 {
1693         size_t len = stackblocksize();
1694         growstackblock();
1695         return (char *)stackblock() + len;
1696 }
1697
1698 /*
1699  * Called from CHECKSTRSPACE.
1700  */
1701 static char *
1702 makestrspace(size_t newlen, char *p)
1703 {
1704         size_t len = p - g_stacknxt;
1705         size_t size;
1706
1707         for (;;) {
1708                 size_t nleft;
1709
1710                 size = stackblocksize();
1711                 nleft = size - len;
1712                 if (nleft >= newlen)
1713                         break;
1714                 growstackblock();
1715         }
1716         return (char *)stackblock() + len;
1717 }
1718
1719 static char *
1720 stack_nputstr(const char *s, size_t n, char *p)
1721 {
1722         p = makestrspace(n, p);
1723         p = (char *)mempcpy(p, s, n);
1724         return p;
1725 }
1726
1727 static char *
1728 stack_putstr(const char *s, char *p)
1729 {
1730         return stack_nputstr(s, strlen(s), p);
1731 }
1732
1733 static char *
1734 _STPUTC(int c, char *p)
1735 {
1736         if (p == sstrend)
1737                 p = growstackstr();
1738         *p++ = c;
1739         return p;
1740 }
1741
1742 #define STARTSTACKSTR(p)        ((p) = stackblock())
1743 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1744 #define CHECKSTRSPACE(n, p) do { \
1745         char *q = (p); \
1746         size_t l = (n); \
1747         size_t m = sstrend - q; \
1748         if (l > m) \
1749                 (p) = makestrspace(l, q); \
1750 } while (0)
1751 #define USTPUTC(c, p)           (*(p)++ = (c))
1752 #define STACKSTRNUL(p) do { \
1753         if ((p) == sstrend) \
1754                 (p) = growstackstr(); \
1755         *(p) = '\0'; \
1756 } while (0)
1757 #define STUNPUTC(p)             (--(p))
1758 #define STTOPC(p)               ((p)[-1])
1759 #define STADJUST(amount, p)     ((p) += (amount))
1760
1761 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1762 #define ungrabstackstr(s, p)    stunalloc(s)
1763 #define stackstrend()           ((void *)sstrend)
1764
1765
1766 /* ============ String helpers */
1767
1768 /*
1769  * prefix -- see if pfx is a prefix of string.
1770  */
1771 static char *
1772 prefix(const char *string, const char *pfx)
1773 {
1774         while (*pfx) {
1775                 if (*pfx++ != *string++)
1776                         return NULL;
1777         }
1778         return (char *) string;
1779 }
1780
1781 /*
1782  * Check for a valid number.  This should be elsewhere.
1783  */
1784 static int
1785 is_number(const char *p)
1786 {
1787         do {
1788                 if (!isdigit(*p))
1789                         return 0;
1790         } while (*++p != '\0');
1791         return 1;
1792 }
1793
1794 /*
1795  * Convert a string of digits to an integer, printing an error message on
1796  * failure.
1797  */
1798 static int
1799 number(const char *s)
1800 {
1801         if (!is_number(s))
1802                 ash_msg_and_raise_error(msg_illnum, s);
1803         return atoi(s);
1804 }
1805
1806 /*
1807  * Produce a single quoted string suitable as input to the shell.
1808  * The return string is allocated on the stack.
1809  */
1810 static char *
1811 single_quote(const char *s)
1812 {
1813         char *p;
1814
1815         STARTSTACKSTR(p);
1816
1817         do {
1818                 char *q;
1819                 size_t len;
1820
1821                 len = strchrnul(s, '\'') - s;
1822
1823                 q = p = makestrspace(len + 3, p);
1824
1825                 *q++ = '\'';
1826                 q = (char *)mempcpy(q, s, len);
1827                 *q++ = '\'';
1828                 s += len;
1829
1830                 STADJUST(q - p, p);
1831
1832                 if (*s != '\'')
1833                         break;
1834                 len = 0;
1835                 do len++; while (*++s == '\'');
1836
1837                 q = p = makestrspace(len + 3, p);
1838
1839                 *q++ = '"';
1840                 q = (char *)mempcpy(q, s - len, len);
1841                 *q++ = '"';
1842
1843                 STADJUST(q - p, p);
1844         } while (*s);
1845
1846         USTPUTC('\0', p);
1847
1848         return stackblock();
1849 }
1850
1851 /*
1852  * Produce a possibly single quoted string suitable as input to the shell.
1853  * If quoting was done, the return string is allocated on the stack,
1854  * otherwise a pointer to the original string is returned.
1855  */
1856 static const char *
1857 maybe_single_quote(const char *s)
1858 {
1859         const char *p = s;
1860
1861         while (*p) {
1862                 /* Assuming ACSII */
1863                 /* quote ctrl_chars space !"#$%&'()* */
1864                 if (*p < '+')
1865                         goto need_quoting;
1866                 /* quote ;<=>? */
1867                 if (*p >= ';' && *p <= '?')
1868                         goto need_quoting;
1869                 /* quote `[\ */
1870                 if (*p == '`')
1871                         goto need_quoting;
1872                 if (*p == '[')
1873                         goto need_quoting;
1874                 if (*p == '\\')
1875                         goto need_quoting;
1876                 /* quote {|}~ DEL and high bytes */
1877                 if (*p > 'z')
1878                         goto need_quoting;
1879                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1880                 /* TODO: maybe avoid quoting % */
1881                 p++;
1882         }
1883         return s;
1884
1885  need_quoting:
1886         return single_quote(s);
1887 }
1888
1889
1890 /* ============ nextopt */
1891
1892 static char **argptr;                  /* argument list for builtin commands */
1893 static char *optionarg;                /* set by nextopt (like getopt) */
1894 static char *optptr;                   /* used by nextopt */
1895
1896 /*
1897  * XXX - should get rid of. Have all builtins use getopt(3).
1898  * The library getopt must have the BSD extension static variable
1899  * "optreset", otherwise it can't be used within the shell safely.
1900  *
1901  * Standard option processing (a la getopt) for builtin routines.
1902  * The only argument that is passed to nextopt is the option string;
1903  * the other arguments are unnecessary. It returns the character,
1904  * or '\0' on end of input.
1905  */
1906 static int
1907 nextopt(const char *optstring)
1908 {
1909         char *p;
1910         const char *q;
1911         char c;
1912
1913         p = optptr;
1914         if (p == NULL || *p == '\0') {
1915                 /* We ate entire "-param", take next one */
1916                 p = *argptr;
1917                 if (p == NULL)
1918                         return '\0';
1919                 if (*p != '-')
1920                         return '\0';
1921                 if (*++p == '\0') /* just "-" ? */
1922                         return '\0';
1923                 argptr++;
1924                 if (LONE_DASH(p)) /* "--" ? */
1925                         return '\0';
1926                 /* p => next "-param" */
1927         }
1928         /* p => some option char in the middle of a "-param" */
1929         c = *p++;
1930         for (q = optstring; *q != c;) {
1931                 if (*q == '\0')
1932                         ash_msg_and_raise_error("illegal option -%c", c);
1933                 if (*++q == ':')
1934                         q++;
1935         }
1936         if (*++q == ':') {
1937                 if (*p == '\0') {
1938                         p = *argptr++;
1939                         if (p == NULL)
1940                                 ash_msg_and_raise_error("no arg for -%c option", c);
1941                 }
1942                 optionarg = p;
1943                 p = NULL;
1944         }
1945         optptr = p;
1946         return c;
1947 }
1948
1949
1950 /* ============ Shell variables */
1951
1952 struct shparam {
1953         int nparam;             /* # of positional parameters (without $0) */
1954 #if ENABLE_ASH_GETOPTS
1955         int optind;             /* next parameter to be processed by getopts */
1956         int optoff;             /* used by getopts */
1957 #endif
1958         unsigned char malloced; /* if parameter list dynamically allocated */
1959         char **p;               /* parameter list */
1960 };
1961
1962 /*
1963  * Free the list of positional parameters.
1964  */
1965 static void
1966 freeparam(volatile struct shparam *param)
1967 {
1968         if (param->malloced) {
1969                 char **ap, **ap1;
1970                 ap = ap1 = param->p;
1971                 while (*ap)
1972                         free(*ap++);
1973                 free(ap1);
1974         }
1975 }
1976
1977 #if ENABLE_ASH_GETOPTS
1978 static void FAST_FUNC getoptsreset(const char *value);
1979 #endif
1980
1981 struct var {
1982         struct var *next;               /* next entry in hash list */
1983         int flags;                      /* flags are defined above */
1984         const char *var_text;           /* name=value */
1985         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1986                                         /* the variable gets set/unset */
1987 };
1988
1989 struct localvar {
1990         struct localvar *next;          /* next local variable in list */
1991         struct var *vp;                 /* the variable that was made local */
1992         int flags;                      /* saved flags */
1993         const char *text;               /* saved text */
1994 };
1995
1996 /* flags */
1997 #define VEXPORT         0x01    /* variable is exported */
1998 #define VREADONLY       0x02    /* variable cannot be modified */
1999 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2000 #define VTEXTFIXED      0x08    /* text is statically allocated */
2001 #define VSTACK          0x10    /* text is allocated on the stack */
2002 #define VUNSET          0x20    /* the variable is not set */
2003 #define VNOFUNC         0x40    /* don't call the callback function */
2004 #define VNOSET          0x80    /* do not set variable - just readonly test */
2005 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2006 #if ENABLE_ASH_RANDOM_SUPPORT
2007 # define VDYNAMIC       0x200   /* dynamic variable */
2008 #else
2009 # define VDYNAMIC       0
2010 #endif
2011
2012
2013 /* Need to be before varinit_data[] */
2014 #if ENABLE_LOCALE_SUPPORT
2015 static void FAST_FUNC
2016 change_lc_all(const char *value)
2017 {
2018         if (value && *value != '\0')
2019                 setlocale(LC_ALL, value);
2020 }
2021 static void FAST_FUNC
2022 change_lc_ctype(const char *value)
2023 {
2024         if (value && *value != '\0')
2025                 setlocale(LC_CTYPE, value);
2026 }
2027 #endif
2028 #if ENABLE_ASH_MAIL
2029 static void chkmail(void);
2030 static void changemail(const char *var_value) FAST_FUNC;
2031 #else
2032 # define chkmail()  ((void)0)
2033 #endif
2034 static void changepath(const char *) FAST_FUNC;
2035 #if ENABLE_ASH_RANDOM_SUPPORT
2036 static void change_random(const char *) FAST_FUNC;
2037 #endif
2038
2039 static const struct {
2040         int flags;
2041         const char *var_text;
2042         void (*var_func)(const char *) FAST_FUNC;
2043 } varinit_data[] = {
2044         /*
2045          * Note: VEXPORT would not work correctly here for NOFORK applets:
2046          * some environment strings may be constant.
2047          */
2048         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2049 #if ENABLE_ASH_MAIL
2050         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2051         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2052 #endif
2053         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2054         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2055         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2056         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2057 #if ENABLE_ASH_GETOPTS
2058         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2059 #endif
2060         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2061 #if ENABLE_ASH_RANDOM_SUPPORT
2062         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2063 #endif
2064 #if ENABLE_LOCALE_SUPPORT
2065         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2066         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2067 #endif
2068 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2069         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2070 #endif
2071 };
2072
2073 struct redirtab;
2074
2075 struct globals_var {
2076         struct shparam shellparam;      /* $@ current positional parameters */
2077         struct redirtab *redirlist;
2078         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2079         struct var *vartab[VTABSIZE];
2080         struct var varinit[ARRAY_SIZE(varinit_data)];
2081         int lineno;
2082         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2083 };
2084 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2085 #define G_var (*ash_ptr_to_globals_var)
2086 #define shellparam    (G_var.shellparam   )
2087 //#define redirlist     (G_var.redirlist    )
2088 #define preverrout_fd (G_var.preverrout_fd)
2089 #define vartab        (G_var.vartab       )
2090 #define varinit       (G_var.varinit      )
2091 #define lineno        (G_var.lineno       )
2092 #define linenovar     (G_var.linenovar    )
2093 #define vifs      varinit[0]
2094 #if ENABLE_ASH_MAIL
2095 # define vmail    (&vifs)[1]
2096 # define vmpath   (&vmail)[1]
2097 # define vpath    (&vmpath)[1]
2098 #else
2099 # define vpath    (&vifs)[1]
2100 #endif
2101 #define vps1      (&vpath)[1]
2102 #define vps2      (&vps1)[1]
2103 #define vps4      (&vps2)[1]
2104 #if ENABLE_ASH_GETOPTS
2105 # define voptind  (&vps4)[1]
2106 # define vlineno  (&voptind)[1]
2107 # if ENABLE_ASH_RANDOM_SUPPORT
2108 #  define vrandom (&vlineno)[1]
2109 # endif
2110 #else
2111 # define vlineno  (&vps4)[1]
2112 # if ENABLE_ASH_RANDOM_SUPPORT
2113 #  define vrandom (&vlineno)[1]
2114 # endif
2115 #endif
2116 #define INIT_G_var() do { \
2117         unsigned i; \
2118         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2119         barrier(); \
2120         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2121                 varinit[i].flags    = varinit_data[i].flags; \
2122                 varinit[i].var_text = varinit_data[i].var_text; \
2123                 varinit[i].var_func = varinit_data[i].var_func; \
2124         } \
2125         strcpy(linenovar, "LINENO="); \
2126         vlineno.var_text = linenovar; \
2127 } while (0)
2128
2129 /*
2130  * The following macros access the values of the above variables.
2131  * They have to skip over the name.  They return the null string
2132  * for unset variables.
2133  */
2134 #define ifsval()        (vifs.var_text + 4)
2135 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2136 #if ENABLE_ASH_MAIL
2137 # define mailval()      (vmail.var_text + 5)
2138 # define mpathval()     (vmpath.var_text + 9)
2139 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2140 #endif
2141 #define pathval()       (vpath.var_text + 5)
2142 #define ps1val()        (vps1.var_text + 4)
2143 #define ps2val()        (vps2.var_text + 4)
2144 #define ps4val()        (vps4.var_text + 4)
2145 #if ENABLE_ASH_GETOPTS
2146 # define optindval()    (voptind.var_text + 7)
2147 #endif
2148
2149 #if ENABLE_ASH_GETOPTS
2150 static void FAST_FUNC
2151 getoptsreset(const char *value)
2152 {
2153         shellparam.optind = 1;
2154         if (is_number(value))
2155                 shellparam.optind = number(value) ?: 1;
2156         shellparam.optoff = -1;
2157 }
2158 #endif
2159
2160 /*
2161  * Compares two strings up to the first = or '\0'.  The first
2162  * string must be terminated by '='; the second may be terminated by
2163  * either '=' or '\0'.
2164  */
2165 static int
2166 varcmp(const char *p, const char *q)
2167 {
2168         int c, d;
2169
2170         while ((c = *p) == (d = *q)) {
2171                 if (c == '\0' || c == '=')
2172                         goto out;
2173                 p++;
2174                 q++;
2175         }
2176         if (c == '=')
2177                 c = '\0';
2178         if (d == '=')
2179                 d = '\0';
2180  out:
2181         return c - d;
2182 }
2183
2184 /*
2185  * Find the appropriate entry in the hash table from the name.
2186  */
2187 static struct var **
2188 hashvar(const char *p)
2189 {
2190         unsigned hashval;
2191
2192         hashval = ((unsigned char) *p) << 4;
2193         while (*p && *p != '=')
2194                 hashval += (unsigned char) *p++;
2195         return &vartab[hashval % VTABSIZE];
2196 }
2197
2198 static int
2199 vpcmp(const void *a, const void *b)
2200 {
2201         return varcmp(*(const char **)a, *(const char **)b);
2202 }
2203
2204 /*
2205  * This routine initializes the builtin variables.
2206  */
2207 static void
2208 initvar(void)
2209 {
2210         struct var *vp;
2211         struct var *end;
2212         struct var **vpp;
2213
2214         /*
2215          * PS1 depends on uid
2216          */
2217 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2218         vps1.var_text = "PS1=\\w \\$ ";
2219 #else
2220         if (!geteuid())
2221                 vps1.var_text = "PS1=# ";
2222 #endif
2223         vp = varinit;
2224         end = vp + ARRAY_SIZE(varinit);
2225         do {
2226                 vpp = hashvar(vp->var_text);
2227                 vp->next = *vpp;
2228                 *vpp = vp;
2229         } while (++vp < end);
2230 }
2231
2232 static struct var **
2233 findvar(struct var **vpp, const char *name)
2234 {
2235         for (; *vpp; vpp = &(*vpp)->next) {
2236                 if (varcmp((*vpp)->var_text, name) == 0) {
2237                         break;
2238                 }
2239         }
2240         return vpp;
2241 }
2242
2243 /*
2244  * Find the value of a variable.  Returns NULL if not set.
2245  */
2246 static const char* FAST_FUNC
2247 lookupvar(const char *name)
2248 {
2249         struct var *v;
2250
2251         v = *findvar(hashvar(name), name);
2252         if (v) {
2253 #if ENABLE_ASH_RANDOM_SUPPORT
2254         /*
2255          * Dynamic variables are implemented roughly the same way they are
2256          * in bash. Namely, they're "special" so long as they aren't unset.
2257          * As soon as they're unset, they're no longer dynamic, and dynamic
2258          * lookup will no longer happen at that point. -- PFM.
2259          */
2260                 if (v->flags & VDYNAMIC)
2261                         v->var_func(NULL);
2262 #endif
2263                 if (!(v->flags & VUNSET)) {
2264                         if (v == &vlineno && v->var_text == linenovar) {
2265                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2266                         }
2267                         return var_end(v->var_text);
2268                 }
2269         }
2270         return NULL;
2271 }
2272
2273 #if ENABLE_UNICODE_SUPPORT
2274 static void
2275 reinit_unicode_for_ash(void)
2276 {
2277         /* Unicode support should be activated even if LANG is set
2278          * _during_ shell execution, not only if it was set when
2279          * shell was started. Therefore, re-check LANG every time:
2280          */
2281         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2282          || ENABLE_UNICODE_USING_LOCALE
2283         ) {
2284                 const char *s = lookupvar("LC_ALL");
2285                 if (!s) s = lookupvar("LC_CTYPE");
2286                 if (!s) s = lookupvar("LANG");
2287                 reinit_unicode(s);
2288         }
2289 }
2290 #else
2291 # define reinit_unicode_for_ash() ((void)0)
2292 #endif
2293
2294 /*
2295  * Search the environment of a builtin command.
2296  */
2297 static ALWAYS_INLINE const char *
2298 bltinlookup(const char *name)
2299 {
2300         return lookupvar(name);
2301 }
2302
2303 /*
2304  * Same as setvar except that the variable and value are passed in
2305  * the first argument as name=value.  Since the first argument will
2306  * be actually stored in the table, it should not be a string that
2307  * will go away.
2308  * Called with interrupts off.
2309  */
2310 static struct var *
2311 setvareq(char *s, int flags)
2312 {
2313         struct var *vp, **vpp;
2314
2315         vpp = hashvar(s);
2316         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2317         vpp = findvar(vpp, s);
2318         vp = *vpp;
2319         if (vp) {
2320                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2321                         const char *n;
2322
2323                         if (flags & VNOSAVE)
2324                                 free(s);
2325                         n = vp->var_text;
2326                         exitstatus = 1;
2327                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2328                 }
2329
2330                 if (flags & VNOSET)
2331                         goto out;
2332
2333                 if (vp->var_func && !(flags & VNOFUNC))
2334                         vp->var_func(var_end(s));
2335
2336                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2337                         free((char*)vp->var_text);
2338
2339                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2340                         *vpp = vp->next;
2341                         free(vp);
2342  out_free:
2343                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2344                                 free(s);
2345                         goto out;
2346                 }
2347
2348                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2349         } else {
2350                 /* variable s is not found */
2351                 if (flags & VNOSET)
2352                         goto out;
2353                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2354                         goto out_free;
2355                 vp = ckzalloc(sizeof(*vp));
2356                 vp->next = *vpp;
2357                 /*vp->func = NULL; - ckzalloc did it */
2358                 *vpp = vp;
2359         }
2360         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2361                 s = ckstrdup(s);
2362         vp->var_text = s;
2363         vp->flags = flags;
2364
2365  out:
2366         return vp;
2367 }
2368
2369 /*
2370  * Set the value of a variable.  The flags argument is ored with the
2371  * flags of the variable.  If val is NULL, the variable is unset.
2372  */
2373 static struct var *
2374 setvar(const char *name, const char *val, int flags)
2375 {
2376         const char *q;
2377         char *p;
2378         char *nameeq;
2379         size_t namelen;
2380         size_t vallen;
2381         struct var *vp;
2382
2383         q = endofname(name);
2384         p = strchrnul(q, '=');
2385         namelen = p - name;
2386         if (!namelen || p != q)
2387                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2388         vallen = 0;
2389         if (val == NULL) {
2390                 flags |= VUNSET;
2391         } else {
2392                 vallen = strlen(val);
2393         }
2394
2395         INT_OFF;
2396         nameeq = ckmalloc(namelen + vallen + 2);
2397         p = mempcpy(nameeq, name, namelen);
2398         if (val) {
2399                 *p++ = '=';
2400                 p = mempcpy(p, val, vallen);
2401         }
2402         *p = '\0';
2403         vp = setvareq(nameeq, flags | VNOSAVE);
2404         INT_ON;
2405
2406         return vp;
2407 }
2408
2409 static void FAST_FUNC
2410 setvar0(const char *name, const char *val)
2411 {
2412         setvar(name, val, 0);
2413 }
2414
2415 /*
2416  * Unset the specified variable.
2417  */
2418 static void
2419 unsetvar(const char *s)
2420 {
2421         setvar(s, NULL, 0);
2422 }
2423
2424 /*
2425  * Process a linked list of variable assignments.
2426  */
2427 static void
2428 listsetvar(struct strlist *list_set_var, int flags)
2429 {
2430         struct strlist *lp = list_set_var;
2431
2432         if (!lp)
2433                 return;
2434         INT_OFF;
2435         do {
2436                 setvareq(lp->text, flags);
2437                 lp = lp->next;
2438         } while (lp);
2439         INT_ON;
2440 }
2441
2442 /*
2443  * Generate a list of variables satisfying the given conditions.
2444  */
2445 #if !ENABLE_FEATURE_SH_NOFORK
2446 # define listvars(on, off, lp, end) listvars(on, off, end)
2447 #endif
2448 static char **
2449 listvars(int on, int off, struct strlist *lp, char ***end)
2450 {
2451         struct var **vpp;
2452         struct var *vp;
2453         char **ep;
2454         int mask;
2455
2456         STARTSTACKSTR(ep);
2457         vpp = vartab;
2458         mask = on | off;
2459         do {
2460                 for (vp = *vpp; vp; vp = vp->next) {
2461                         if ((vp->flags & mask) == on) {
2462 #if ENABLE_FEATURE_SH_NOFORK
2463                                 /* If variable with the same name is both
2464                                  * exported and temporarily set for a command:
2465                                  *  export ZVAR=5
2466                                  *  ZVAR=6 printenv
2467                                  * then "ZVAR=6" will be both in vartab and
2468                                  * lp lists. Do not pass it twice to printenv.
2469                                  */
2470                                 struct strlist *lp1 = lp;
2471                                 while (lp1) {
2472                                         if (strcmp(lp1->text, vp->var_text) == 0)
2473                                                 goto skip;
2474                                         lp1 = lp1->next;
2475                                 }
2476 #endif
2477                                 if (ep == stackstrend())
2478                                         ep = growstackstr();
2479                                 *ep++ = (char*)vp->var_text;
2480 #if ENABLE_FEATURE_SH_NOFORK
2481  skip: ;
2482 #endif
2483                         }
2484                 }
2485         } while (++vpp < vartab + VTABSIZE);
2486
2487 #if ENABLE_FEATURE_SH_NOFORK
2488         while (lp) {
2489                 if (ep == stackstrend())
2490                         ep = growstackstr();
2491                 *ep++ = lp->text;
2492                 lp = lp->next;
2493         }
2494 #endif
2495
2496         if (ep == stackstrend())
2497                 ep = growstackstr();
2498         if (end)
2499                 *end = ep;
2500         *ep++ = NULL;
2501         return grabstackstr(ep);
2502 }
2503
2504
2505 /* ============ Path search helper
2506  *
2507  * The variable path (passed by reference) should be set to the start
2508  * of the path before the first call; path_advance will update
2509  * this value as it proceeds.  Successive calls to path_advance will return
2510  * the possible path expansions in sequence.  If an option (indicated by
2511  * a percent sign) appears in the path entry then the global variable
2512  * pathopt will be set to point to it; otherwise pathopt will be set to
2513  * NULL.
2514  */
2515 static const char *pathopt;     /* set by path_advance */
2516
2517 static char *
2518 path_advance(const char **path, const char *name)
2519 {
2520         const char *p;
2521         char *q;
2522         const char *start;
2523         size_t len;
2524
2525         if (*path == NULL)
2526                 return NULL;
2527         start = *path;
2528         for (p = start; *p && *p != ':' && *p != '%'; p++)
2529                 continue;
2530         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2531         while (stackblocksize() < len)
2532                 growstackblock();
2533         q = stackblock();
2534         if (p != start) {
2535                 q = mempcpy(q, start, p - start);
2536                 *q++ = '/';
2537         }
2538         strcpy(q, name);
2539         pathopt = NULL;
2540         if (*p == '%') {
2541                 pathopt = ++p;
2542                 while (*p && *p != ':')
2543                         p++;
2544         }
2545         if (*p == ':')
2546                 *path = p + 1;
2547         else
2548                 *path = NULL;
2549         return stalloc(len);
2550 }
2551
2552
2553 /* ============ Prompt */
2554
2555 static smallint doprompt;                   /* if set, prompt the user */
2556 static smallint needprompt;                 /* true if interactive and at start of line */
2557
2558 #if ENABLE_FEATURE_EDITING
2559 static line_input_t *line_input_state;
2560 static const char *cmdedit_prompt;
2561 static void
2562 putprompt(const char *s)
2563 {
2564         if (ENABLE_ASH_EXPAND_PRMT) {
2565                 free((char*)cmdedit_prompt);
2566                 cmdedit_prompt = ckstrdup(s);
2567                 return;
2568         }
2569         cmdedit_prompt = s;
2570 }
2571 #else
2572 static void
2573 putprompt(const char *s)
2574 {
2575         out2str(s);
2576 }
2577 #endif
2578
2579 /* expandstr() needs parsing machinery, so it is far away ahead... */
2580 static const char *expandstr(const char *ps, int syntax_type);
2581 /* Values for syntax param */
2582 #define BASESYNTAX 0    /* not in quotes */
2583 #define DQSYNTAX   1    /* in double quotes */
2584 #define SQSYNTAX   2    /* in single quotes */
2585 #define ARISYNTAX  3    /* in arithmetic */
2586 #if ENABLE_ASH_EXPAND_PRMT
2587 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2588 #endif
2589 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2590
2591 /*
2592  * called by editline -- any expansions to the prompt should be added here.
2593  */
2594 static void
2595 setprompt_if(smallint do_set, int whichprompt)
2596 {
2597         const char *prompt;
2598         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2599
2600         if (!do_set)
2601                 return;
2602
2603         needprompt = 0;
2604
2605         switch (whichprompt) {
2606         case 1:
2607                 prompt = ps1val();
2608                 break;
2609         case 2:
2610                 prompt = ps2val();
2611                 break;
2612         default:                        /* 0 */
2613                 prompt = nullstr;
2614         }
2615 #if ENABLE_ASH_EXPAND_PRMT
2616         pushstackmark(&smark, stackblocksize());
2617         putprompt(expandstr(prompt, PSSYNTAX));
2618         popstackmark(&smark);
2619 #else
2620         putprompt(prompt);
2621 #endif
2622 }
2623
2624
2625 /* ============ The cd and pwd commands */
2626
2627 #define CD_PHYSICAL 1
2628 #define CD_PRINT 2
2629
2630 static int
2631 cdopt(void)
2632 {
2633         int flags = 0;
2634         int i, j;
2635
2636         j = 'L';
2637         while ((i = nextopt("LP")) != '\0') {
2638                 if (i != j) {
2639                         flags ^= CD_PHYSICAL;
2640                         j = i;
2641                 }
2642         }
2643
2644         return flags;
2645 }
2646
2647 /*
2648  * Update curdir (the name of the current directory) in response to a
2649  * cd command.
2650  */
2651 static const char *
2652 updatepwd(const char *dir)
2653 {
2654         char *new;
2655         char *p;
2656         char *cdcomppath;
2657         const char *lim;
2658
2659         cdcomppath = sstrdup(dir);
2660         STARTSTACKSTR(new);
2661         if (*dir != '/') {
2662                 if (curdir == nullstr)
2663                         return 0;
2664                 new = stack_putstr(curdir, new);
2665         }
2666         new = makestrspace(strlen(dir) + 2, new);
2667         lim = (char *)stackblock() + 1;
2668         if (*dir != '/') {
2669                 if (new[-1] != '/')
2670                         USTPUTC('/', new);
2671                 if (new > lim && *lim == '/')
2672                         lim++;
2673         } else {
2674                 USTPUTC('/', new);
2675                 cdcomppath++;
2676                 if (dir[1] == '/' && dir[2] != '/') {
2677                         USTPUTC('/', new);
2678                         cdcomppath++;
2679                         lim++;
2680                 }
2681         }
2682         p = strtok(cdcomppath, "/");
2683         while (p) {
2684                 switch (*p) {
2685                 case '.':
2686                         if (p[1] == '.' && p[2] == '\0') {
2687                                 while (new > lim) {
2688                                         STUNPUTC(new);
2689                                         if (new[-1] == '/')
2690                                                 break;
2691                                 }
2692                                 break;
2693                         }
2694                         if (p[1] == '\0')
2695                                 break;
2696                         /* fall through */
2697                 default:
2698                         new = stack_putstr(p, new);
2699                         USTPUTC('/', new);
2700                 }
2701                 p = strtok(NULL, "/");
2702         }
2703         if (new > lim)
2704                 STUNPUTC(new);
2705         *new = 0;
2706         return stackblock();
2707 }
2708
2709 /*
2710  * Find out what the current directory is. If we already know the current
2711  * directory, this routine returns immediately.
2712  */
2713 static char *
2714 getpwd(void)
2715 {
2716         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2717         return dir ? dir : nullstr;
2718 }
2719
2720 static void
2721 setpwd(const char *val, int setold)
2722 {
2723         char *oldcur, *dir;
2724
2725         oldcur = dir = curdir;
2726
2727         if (setold) {
2728                 setvar("OLDPWD", oldcur, VEXPORT);
2729         }
2730         INT_OFF;
2731         if (physdir != nullstr) {
2732                 if (physdir != oldcur)
2733                         free(physdir);
2734                 physdir = nullstr;
2735         }
2736         if (oldcur == val || !val) {
2737                 char *s = getpwd();
2738                 physdir = s;
2739                 if (!val)
2740                         dir = s;
2741         } else
2742                 dir = ckstrdup(val);
2743         if (oldcur != dir && oldcur != nullstr) {
2744                 free(oldcur);
2745         }
2746         curdir = dir;
2747         INT_ON;
2748         setvar("PWD", dir, VEXPORT);
2749 }
2750
2751 static void hashcd(void);
2752
2753 /*
2754  * Actually do the chdir.  We also call hashcd to let other routines
2755  * know that the current directory has changed.
2756  */
2757 static int
2758 docd(const char *dest, int flags)
2759 {
2760         const char *dir = NULL;
2761         int err;
2762
2763         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2764
2765         INT_OFF;
2766         if (!(flags & CD_PHYSICAL)) {
2767                 dir = updatepwd(dest);
2768                 if (dir)
2769                         dest = dir;
2770         }
2771         err = chdir(dest);
2772         if (err)
2773                 goto out;
2774         setpwd(dir, 1);
2775         hashcd();
2776  out:
2777         INT_ON;
2778         return err;
2779 }
2780
2781 static int FAST_FUNC
2782 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2783 {
2784         const char *dest;
2785         const char *path;
2786         const char *p;
2787         char c;
2788         struct stat statb;
2789         int flags;
2790
2791         flags = cdopt();
2792         dest = *argptr;
2793         if (!dest)
2794                 dest = bltinlookup("HOME");
2795         else if (LONE_DASH(dest)) {
2796                 dest = bltinlookup("OLDPWD");
2797                 flags |= CD_PRINT;
2798         }
2799         if (!dest)
2800                 dest = nullstr;
2801         if (*dest == '/')
2802                 goto step6;
2803         if (*dest == '.') {
2804                 c = dest[1];
2805  dotdot:
2806                 switch (c) {
2807                 case '\0':
2808                 case '/':
2809                         goto step6;
2810                 case '.':
2811                         c = dest[2];
2812                         if (c != '.')
2813                                 goto dotdot;
2814                 }
2815         }
2816         if (!*dest)
2817                 dest = ".";
2818         path = bltinlookup("CDPATH");
2819         while (path) {
2820                 c = *path;
2821                 p = path_advance(&path, dest);
2822                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2823                         if (c && c != ':')
2824                                 flags |= CD_PRINT;
2825  docd:
2826                         if (!docd(p, flags))
2827                                 goto out;
2828                         goto err;
2829                 }
2830         }
2831
2832  step6:
2833         p = dest;
2834         goto docd;
2835
2836  err:
2837         ash_msg_and_raise_perror("can't cd to %s", dest);
2838         /* NOTREACHED */
2839  out:
2840         if (flags & CD_PRINT)
2841                 out1fmt("%s\n", curdir);
2842         return 0;
2843 }
2844
2845 static int FAST_FUNC
2846 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2847 {
2848         int flags;
2849         const char *dir = curdir;
2850
2851         flags = cdopt();
2852         if (flags) {
2853                 if (physdir == nullstr)
2854                         setpwd(dir, 0);
2855                 dir = physdir;
2856         }
2857         out1fmt("%s\n", dir);
2858         return 0;
2859 }
2860
2861
2862 /* ============ ... */
2863
2864
2865 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2866
2867 /* Syntax classes */
2868 #define CWORD     0             /* character is nothing special */
2869 #define CNL       1             /* newline character */
2870 #define CBACK     2             /* a backslash character */
2871 #define CSQUOTE   3             /* single quote */
2872 #define CDQUOTE   4             /* double quote */
2873 #define CENDQUOTE 5             /* a terminating quote */
2874 #define CBQUOTE   6             /* backwards single quote */
2875 #define CVAR      7             /* a dollar sign */
2876 #define CENDVAR   8             /* a '}' character */
2877 #define CLP       9             /* a left paren in arithmetic */
2878 #define CRP      10             /* a right paren in arithmetic */
2879 #define CENDFILE 11             /* end of file */
2880 #define CCTL     12             /* like CWORD, except it must be escaped */
2881 #define CSPCL    13             /* these terminate a word */
2882 #define CIGN     14             /* character should be ignored */
2883
2884 #define PEOF     256
2885 #if ENABLE_ASH_ALIAS
2886 # define PEOA    257
2887 #endif
2888
2889 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2890
2891 #if ENABLE_FEATURE_SH_MATH
2892 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2893 #else
2894 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2895 #endif
2896 static const uint16_t S_I_T[] ALIGN2 = {
2897 #if ENABLE_ASH_ALIAS
2898         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2899 #endif
2900         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2901         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2902         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2903         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2904         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2905         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2906         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2907         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2908         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2909         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2910         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2911 #if !USE_SIT_FUNCTION
2912         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2913         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2914         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2915 #endif
2916 #undef SIT_ITEM
2917 };
2918 /* Constants below must match table above */
2919 enum {
2920 #if ENABLE_ASH_ALIAS
2921         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2922 #endif
2923         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2924         CNL_CNL_CNL_CNL                    , /*  2 */
2925         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2926         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2927         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2928         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2929         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2930         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2931         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2932         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2933         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2934         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2935         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2936         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2937 };
2938
2939 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2940  * caller must ensure proper cast on it if c is *char_ptr!
2941  */
2942 #if USE_SIT_FUNCTION
2943
2944 static int
2945 SIT(int c, int syntax)
2946 {
2947         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2948         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2949         /*
2950          * This causes '/' to be prepended with CTLESC in dquoted string,
2951          * making "./file"* treated incorrectly because we feed
2952          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2953          * The "homegrown" glob implementation is okay with that,
2954          * but glibc one isn't. With '/' always treated as CWORD,
2955          * both work fine.
2956          */
2957 # if ENABLE_ASH_ALIAS
2958         static const uint8_t syntax_index_table[] ALIGN1 = {
2959                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2960                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2961                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2962                 11, 3                           /* "}~" */
2963         };
2964 # else
2965         static const uint8_t syntax_index_table[] ALIGN1 = {
2966                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2967                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2968                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2969                 10, 2                           /* "}~" */
2970         };
2971 # endif
2972         const char *s;
2973         int indx;
2974
2975         if (c == PEOF)
2976                 return CENDFILE;
2977 # if ENABLE_ASH_ALIAS
2978         if (c == PEOA)
2979                 indx = 0;
2980         else
2981 # endif
2982         {
2983                 /* Cast is purely for paranoia here,
2984                  * just in case someone passed signed char to us */
2985                 if ((unsigned char)c >= CTL_FIRST
2986                  && (unsigned char)c <= CTL_LAST
2987                 ) {
2988                         return CCTL;
2989                 }
2990                 s = strchrnul(spec_symbls, c);
2991                 if (*s == '\0')
2992                         return CWORD;
2993                 indx = syntax_index_table[s - spec_symbls];
2994         }
2995         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2996 }
2997
2998 #else   /* !USE_SIT_FUNCTION */
2999
3000 static const uint8_t syntax_index_table[] ALIGN1 = {
3001         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3002         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3003         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3004         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3005         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3006         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3007         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3008         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3009         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3010         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3011         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3012         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3013         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3014         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3015         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3016         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3017         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3018         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3019         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3020         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3021         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3022         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3023         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3024         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3025         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3029         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3030         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3031         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3032         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3033         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3034         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3035         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3036         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3037         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3038         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3039         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3040         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3041         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3042         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3043         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3044         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3045         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3046         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3047         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3048         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3049 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3050         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3051         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3053         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3054         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3055         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3056         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3057         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3059         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3060         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3061         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3062         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3063         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3064         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3065         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3066         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3067         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3074         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3075         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3076         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3077         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3078         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3089         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3090         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3092         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3094         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3095         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3096         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3097         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3100         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3102         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3103         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3104         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3105         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3106         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3107         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3108         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3109         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3110         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3111         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3112         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3113         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3114         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3122         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3123         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3124         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3125         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3126         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3127         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3128         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3129         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3130         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3131         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3132         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3133         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3134         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3135         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3136         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3137         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3138         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3139         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3140         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3259         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3260 # if ENABLE_ASH_ALIAS
3261         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3262 # endif
3263 };
3264
3265 #if 1
3266 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3267 #else /* debug version, caught one signed char bug */
3268 # define SIT(c, syntax) \
3269         ({ \
3270                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3271                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3272                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3273                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3274                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3275         })
3276 #endif
3277
3278 #endif  /* !USE_SIT_FUNCTION */
3279
3280
3281 /* ============ Alias handling */
3282
3283 #if ENABLE_ASH_ALIAS
3284
3285 #define ALIASINUSE 1
3286 #define ALIASDEAD  2
3287
3288 struct alias {
3289         struct alias *next;
3290         char *name;
3291         char *val;
3292         int flag;
3293 };
3294
3295
3296 static struct alias **atab; // [ATABSIZE];
3297 #define INIT_G_alias() do { \
3298         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3299 } while (0)
3300
3301
3302 static struct alias **
3303 __lookupalias(const char *name)
3304 {
3305         unsigned int hashval;
3306         struct alias **app;
3307         const char *p;
3308         unsigned int ch;
3309
3310         p = name;
3311
3312         ch = (unsigned char)*p;
3313         hashval = ch << 4;
3314         while (ch) {
3315                 hashval += ch;
3316                 ch = (unsigned char)*++p;
3317         }
3318         app = &atab[hashval % ATABSIZE];
3319
3320         for (; *app; app = &(*app)->next) {
3321                 if (strcmp(name, (*app)->name) == 0) {
3322                         break;
3323                 }
3324         }
3325
3326         return app;
3327 }
3328
3329 static struct alias *
3330 lookupalias(const char *name, int check)
3331 {
3332         struct alias *ap = *__lookupalias(name);
3333
3334         if (check && ap && (ap->flag & ALIASINUSE))
3335                 return NULL;
3336         return ap;
3337 }
3338
3339 static struct alias *
3340 freealias(struct alias *ap)
3341 {
3342         struct alias *next;
3343
3344         if (ap->flag & ALIASINUSE) {
3345                 ap->flag |= ALIASDEAD;
3346                 return ap;
3347         }
3348
3349         next = ap->next;
3350         free(ap->name);
3351         free(ap->val);
3352         free(ap);
3353         return next;
3354 }
3355
3356 static void
3357 setalias(const char *name, const char *val)
3358 {
3359         struct alias *ap, **app;
3360
3361         app = __lookupalias(name);
3362         ap = *app;
3363         INT_OFF;
3364         if (ap) {
3365                 if (!(ap->flag & ALIASINUSE)) {
3366                         free(ap->val);
3367                 }
3368                 ap->val = ckstrdup(val);
3369                 ap->flag &= ~ALIASDEAD;
3370         } else {
3371                 /* not found */
3372                 ap = ckzalloc(sizeof(struct alias));
3373                 ap->name = ckstrdup(name);
3374                 ap->val = ckstrdup(val);
3375                 /*ap->flag = 0; - ckzalloc did it */
3376                 /*ap->next = NULL;*/
3377                 *app = ap;
3378         }
3379         INT_ON;
3380 }
3381
3382 static int
3383 unalias(const char *name)
3384 {
3385         struct alias **app;
3386
3387         app = __lookupalias(name);
3388
3389         if (*app) {
3390                 INT_OFF;
3391                 *app = freealias(*app);
3392                 INT_ON;
3393                 return 0;
3394         }
3395
3396         return 1;
3397 }
3398
3399 static void
3400 rmaliases(void)
3401 {
3402         struct alias *ap, **app;
3403         int i;
3404
3405         INT_OFF;
3406         for (i = 0; i < ATABSIZE; i++) {
3407                 app = &atab[i];
3408                 for (ap = *app; ap; ap = *app) {
3409                         *app = freealias(*app);
3410                         if (ap == *app) {
3411                                 app = &ap->next;
3412                         }
3413                 }
3414         }
3415         INT_ON;
3416 }
3417
3418 static void
3419 printalias(const struct alias *ap)
3420 {
3421         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3422 }
3423
3424 /*
3425  * TODO - sort output
3426  */
3427 static int FAST_FUNC
3428 aliascmd(int argc UNUSED_PARAM, char **argv)
3429 {
3430         char *n, *v;
3431         int ret = 0;
3432         struct alias *ap;
3433
3434         if (!argv[1]) {
3435                 int i;
3436
3437                 for (i = 0; i < ATABSIZE; i++) {
3438                         for (ap = atab[i]; ap; ap = ap->next) {
3439                                 printalias(ap);
3440                         }
3441                 }
3442                 return 0;
3443         }
3444         while ((n = *++argv) != NULL) {
3445                 v = strchr(n+1, '=');
3446                 if (v == NULL) { /* n+1: funny ksh stuff */
3447                         ap = *__lookupalias(n);
3448                         if (ap == NULL) {
3449                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3450                                 ret = 1;
3451                         } else
3452                                 printalias(ap);
3453                 } else {
3454                         *v++ = '\0';
3455                         setalias(n, v);
3456                 }
3457         }
3458
3459         return ret;
3460 }
3461
3462 static int FAST_FUNC
3463 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3464 {
3465         int i;
3466
3467         while (nextopt("a") != '\0') {
3468                 rmaliases();
3469                 return 0;
3470         }
3471         for (i = 0; *argptr; argptr++) {
3472                 if (unalias(*argptr)) {
3473                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3474                         i = 1;
3475                 }
3476         }
3477
3478         return i;
3479 }
3480
3481 #endif /* ASH_ALIAS */
3482
3483
3484 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3485 #define FORK_FG    0
3486 #define FORK_BG    1
3487 #define FORK_NOJOB 2
3488
3489 /* mode flags for showjob(s) */
3490 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3491 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3492 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3493 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3494
3495 /*
3496  * A job structure contains information about a job.  A job is either a
3497  * single process or a set of processes contained in a pipeline.  In the
3498  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3499  * array of pids.
3500  */
3501 struct procstat {
3502         pid_t   ps_pid;         /* process id */
3503         int     ps_status;      /* last process status from wait() */
3504         char    *ps_cmd;        /* text of command being run */
3505 };
3506
3507 struct job {
3508         struct procstat ps0;    /* status of process */
3509         struct procstat *ps;    /* status or processes when more than one */
3510 #if JOBS
3511         int stopstatus;         /* status of a stopped job */
3512 #endif
3513         unsigned nprocs;        /* number of processes */
3514
3515 #define JOBRUNNING      0       /* at least one proc running */
3516 #define JOBSTOPPED      1       /* all procs are stopped */
3517 #define JOBDONE         2       /* all procs are completed */
3518         unsigned
3519                 state: 8,
3520 #if JOBS
3521                 sigint: 1,      /* job was killed by SIGINT */
3522                 jobctl: 1,      /* job running under job control */
3523 #endif
3524                 waited: 1,      /* true if this entry has been waited for */
3525                 used: 1,        /* true if this entry is in used */
3526                 changed: 1;     /* true if status has changed */
3527         struct job *prev_job;   /* previous job */
3528 };
3529
3530 static struct job *makejob(/*union node *,*/ int);
3531 static int forkshell(struct job *, union node *, int);
3532 static int waitforjob(struct job *);
3533
3534 #if !JOBS
3535 enum { doing_jobctl = 0 };
3536 #define setjobctl(on) do {} while (0)
3537 #else
3538 static smallint doing_jobctl; //references:8
3539 static void setjobctl(int);
3540 #endif
3541
3542 /*
3543  * Ignore a signal.
3544  */
3545 static void
3546 ignoresig(int signo)
3547 {
3548         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3549         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3550                 /* No, need to do it */
3551                 signal(signo, SIG_IGN);
3552         }
3553         sigmode[signo - 1] = S_HARD_IGN;
3554 }
3555
3556 /*
3557  * Only one usage site - in setsignal()
3558  */
3559 static void
3560 signal_handler(int signo)
3561 {
3562         if (signo == SIGCHLD) {
3563                 got_sigchld = 1;
3564                 if (!trap[SIGCHLD])
3565                         return;
3566         }
3567
3568         gotsig[signo - 1] = 1;
3569         pending_sig = signo;
3570
3571         if (signo == SIGINT && !trap[SIGINT]) {
3572                 if (!suppress_int) {
3573                         pending_sig = 0;
3574                         raise_interrupt(); /* does not return */
3575                 }
3576                 pending_int = 1;
3577         }
3578 }
3579
3580 /*
3581  * Set the signal handler for the specified signal.  The routine figures
3582  * out what it should be set to.
3583  */
3584 static void
3585 setsignal(int signo)
3586 {
3587         char *t;
3588         char cur_act, new_act;
3589         struct sigaction act;
3590
3591         t = trap[signo];
3592         new_act = S_DFL;
3593         if (t != NULL) { /* trap for this sig is set */
3594                 new_act = S_CATCH;
3595                 if (t[0] == '\0') /* trap is "": ignore this sig */
3596                         new_act = S_IGN;
3597         }
3598
3599         if (rootshell && new_act == S_DFL) {
3600                 switch (signo) {
3601                 case SIGINT:
3602                         if (iflag || minusc || sflag == 0)
3603                                 new_act = S_CATCH;
3604                         break;
3605                 case SIGQUIT:
3606 #if DEBUG
3607                         if (debug)
3608                                 break;
3609 #endif
3610                         /* man bash:
3611                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3612                          * commands run by bash have signal handlers
3613                          * set to the values inherited by the shell
3614                          * from its parent". */
3615                         new_act = S_IGN;
3616                         break;
3617                 case SIGTERM:
3618                         if (iflag)
3619                                 new_act = S_IGN;
3620                         break;
3621 #if JOBS
3622                 case SIGTSTP:
3623                 case SIGTTOU:
3624                         if (mflag)
3625                                 new_act = S_IGN;
3626                         break;
3627 #endif
3628                 }
3629         }
3630         /* if !rootshell, we reset SIGQUIT to DFL,
3631          * whereas we have to restore it to what shell got on entry.
3632          * This is handled by the fact that if signal was IGNored on entry,
3633          * then cur_act is S_HARD_IGN and we never change its sigaction
3634          * (see code below).
3635          */
3636
3637         if (signo == SIGCHLD)
3638                 new_act = S_CATCH;
3639
3640         t = &sigmode[signo - 1];
3641         cur_act = *t;
3642         if (cur_act == 0) {
3643                 /* current setting is not yet known */
3644                 if (sigaction(signo, NULL, &act)) {
3645                         /* pretend it worked; maybe we should give a warning,
3646                          * but other shells don't. We don't alter sigmode,
3647                          * so we retry every time.
3648                          * btw, in Linux it never fails. --vda */
3649                         return;
3650                 }
3651                 if (act.sa_handler == SIG_IGN) {
3652                         cur_act = S_HARD_IGN;
3653                         if (mflag
3654                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3655                         ) {
3656                                 cur_act = S_IGN;   /* don't hard ignore these */
3657                         }
3658                 }
3659                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3660                         /* installing SIG_DFL over SIG_DFL is a no-op */
3661                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3662                         *t = S_DFL;
3663                         return;
3664                 }
3665         }
3666         if (cur_act == S_HARD_IGN || cur_act == new_act)
3667                 return;
3668
3669         *t = new_act;
3670
3671         act.sa_handler = SIG_DFL;
3672         switch (new_act) {
3673         case S_CATCH:
3674                 act.sa_handler = signal_handler;
3675                 break;
3676         case S_IGN:
3677                 act.sa_handler = SIG_IGN;
3678                 break;
3679         }
3680         /* flags and mask matter only if !DFL and !IGN, but we do it
3681          * for all cases for more deterministic behavior:
3682          */
3683         act.sa_flags = 0; //TODO: why not SA_RESTART?
3684         sigfillset(&act.sa_mask);
3685
3686         sigaction_set(signo, &act);
3687 }
3688
3689 /* mode flags for set_curjob */
3690 #define CUR_DELETE 2
3691 #define CUR_RUNNING 1
3692 #define CUR_STOPPED 0
3693
3694 #if JOBS
3695 /* pgrp of shell on invocation */
3696 static int initialpgrp; //references:2
3697 static int ttyfd = -1; //5
3698 #endif
3699 /* array of jobs */
3700 static struct job *jobtab; //5
3701 /* size of array */
3702 static unsigned njobs; //4
3703 /* current job */
3704 static struct job *curjob; //lots
3705 /* number of presumed living untracked jobs */
3706 static int jobless; //4
3707
3708 #if 0
3709 /* Bash has a feature: it restores termios after a successful wait for
3710  * a foreground job which had at least one stopped or sigkilled member.
3711  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3712  * properly restoring tty state. Should we do this too?
3713  * A reproducer: ^Z an interactive python:
3714  *
3715  * # python
3716  * Python 2.7.12 (...)
3717  * >>> ^Z
3718  *      { python leaves tty in -icanon -echo state. We do survive that... }
3719  *  [1]+  Stopped                    python
3720  *      { ...however, next program (python #2) does not survive it well: }
3721  * # python
3722  * Python 2.7.12 (...)
3723  * >>> Traceback (most recent call last):
3724  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3725  *   File "<stdin>", line 1, in <module>
3726  * NameError: name 'qwerty' is not defined
3727  *
3728  * The implementation below is modeled on bash code and seems to work.
3729  * However, I'm not sure we should do this. For one: what if I'd fg
3730  * the stopped python instead? It'll be confused by "restored" tty state.
3731  */
3732 static struct termios shell_tty_info;
3733 static void
3734 get_tty_state(void)
3735 {
3736         if (rootshell && ttyfd >= 0)
3737                 tcgetattr(ttyfd, &shell_tty_info);
3738 }
3739 static void
3740 set_tty_state(void)
3741 {
3742         /* if (rootshell) - caller ensures this */
3743         if (ttyfd >= 0)
3744                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3745 }
3746 static int
3747 job_signal_status(struct job *jp)
3748 {
3749         int status;
3750         unsigned i;
3751         struct procstat *ps = jp->ps;
3752         for (i = 0; i < jp->nprocs; i++) {
3753                 status = ps[i].ps_status;
3754                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3755                         return status;
3756         }
3757         return 0;
3758 }
3759 static void
3760 restore_tty_if_stopped_or_signaled(struct job *jp)
3761 {
3762 //TODO: check what happens if we come from waitforjob() in expbackq()
3763         if (rootshell) {
3764                 int s = job_signal_status(jp);
3765                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3766                         set_tty_state();
3767         }
3768 }
3769 #else
3770 # define get_tty_state() ((void)0)
3771 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3772 #endif
3773
3774 static void
3775 set_curjob(struct job *jp, unsigned mode)
3776 {
3777         struct job *jp1;
3778         struct job **jpp, **curp;
3779
3780         /* first remove from list */
3781         jpp = curp = &curjob;
3782         while (1) {
3783                 jp1 = *jpp;
3784                 if (jp1 == jp)
3785                         break;
3786                 jpp = &jp1->prev_job;
3787         }
3788         *jpp = jp1->prev_job;
3789
3790         /* Then re-insert in correct position */
3791         jpp = curp;
3792         switch (mode) {
3793         default:
3794 #if DEBUG
3795                 abort();
3796 #endif
3797         case CUR_DELETE:
3798                 /* job being deleted */
3799                 break;
3800         case CUR_RUNNING:
3801                 /* newly created job or backgrounded job,
3802                  * put after all stopped jobs.
3803                  */
3804                 while (1) {
3805                         jp1 = *jpp;
3806 #if JOBS
3807                         if (!jp1 || jp1->state != JOBSTOPPED)
3808 #endif
3809                                 break;
3810                         jpp = &jp1->prev_job;
3811                 }
3812                 /* FALLTHROUGH */
3813 #if JOBS
3814         case CUR_STOPPED:
3815 #endif
3816                 /* newly stopped job - becomes curjob */
3817                 jp->prev_job = *jpp;
3818                 *jpp = jp;
3819                 break;
3820         }
3821 }
3822
3823 #if JOBS || DEBUG
3824 static int
3825 jobno(const struct job *jp)
3826 {
3827         return jp - jobtab + 1;
3828 }
3829 #endif
3830
3831 /*
3832  * Convert a job name to a job structure.
3833  */
3834 #if !JOBS
3835 #define getjob(name, getctl) getjob(name)
3836 #endif
3837 static struct job *
3838 getjob(const char *name, int getctl)
3839 {
3840         struct job *jp;
3841         struct job *found;
3842         const char *err_msg = "%s: no such job";
3843         unsigned num;
3844         int c;
3845         const char *p;
3846         char *(*match)(const char *, const char *);
3847
3848         jp = curjob;
3849         p = name;
3850         if (!p)
3851                 goto currentjob;
3852
3853         if (*p != '%')
3854                 goto err;
3855
3856         c = *++p;
3857         if (!c)
3858                 goto currentjob;
3859
3860         if (!p[1]) {
3861                 if (c == '+' || c == '%') {
3862  currentjob:
3863                         err_msg = "No current job";
3864                         goto check;
3865                 }
3866                 if (c == '-') {
3867                         if (jp)
3868                                 jp = jp->prev_job;
3869                         err_msg = "No previous job";
3870  check:
3871                         if (!jp)
3872                                 goto err;
3873                         goto gotit;
3874                 }
3875         }
3876
3877         if (is_number(p)) {
3878                 num = atoi(p);
3879                 if (num > 0 && num <= njobs) {
3880                         jp = jobtab + num - 1;
3881                         if (jp->used)
3882                                 goto gotit;
3883                         goto err;
3884                 }
3885         }
3886
3887         match = prefix;
3888         if (*p == '?') {
3889                 match = strstr;
3890                 p++;
3891         }
3892
3893         found = NULL;
3894         while (jp) {
3895                 if (match(jp->ps[0].ps_cmd, p)) {
3896                         if (found)
3897                                 goto err;
3898                         found = jp;
3899                         err_msg = "%s: ambiguous";
3900                 }
3901                 jp = jp->prev_job;
3902         }
3903         if (!found)
3904                 goto err;
3905         jp = found;
3906
3907  gotit:
3908 #if JOBS
3909         err_msg = "job %s not created under job control";
3910         if (getctl && jp->jobctl == 0)
3911                 goto err;
3912 #endif
3913         return jp;
3914  err:
3915         ash_msg_and_raise_error(err_msg, name);
3916 }
3917
3918 /*
3919  * Mark a job structure as unused.
3920  */
3921 static void
3922 freejob(struct job *jp)
3923 {
3924         struct procstat *ps;
3925         int i;
3926
3927         INT_OFF;
3928         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3929                 if (ps->ps_cmd != nullstr)
3930                         free(ps->ps_cmd);
3931         }
3932         if (jp->ps != &jp->ps0)
3933                 free(jp->ps);
3934         jp->used = 0;
3935         set_curjob(jp, CUR_DELETE);
3936         INT_ON;
3937 }
3938
3939 #if JOBS
3940 static void
3941 xtcsetpgrp(int fd, pid_t pgrp)
3942 {
3943         if (tcsetpgrp(fd, pgrp))
3944                 ash_msg_and_raise_perror("can't set tty process group");
3945 }
3946
3947 /*
3948  * Turn job control on and off.
3949  *
3950  * Note:  This code assumes that the third arg to ioctl is a character
3951  * pointer, which is true on Berkeley systems but not System V.  Since
3952  * System V doesn't have job control yet, this isn't a problem now.
3953  *
3954  * Called with interrupts off.
3955  */
3956 static void
3957 setjobctl(int on)
3958 {
3959         int fd;
3960         int pgrp;
3961
3962         if (on == doing_jobctl || rootshell == 0)
3963                 return;
3964         if (on) {
3965                 int ofd;
3966                 ofd = fd = open(_PATH_TTY, O_RDWR);
3967                 if (fd < 0) {
3968         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3969          * That sometimes helps to acquire controlling tty.
3970          * Obviously, a workaround for bugs when someone
3971          * failed to provide a controlling tty to bash! :) */
3972                         fd = 2;
3973                         while (!isatty(fd))
3974                                 if (--fd < 0)
3975                                         goto out;
3976                 }
3977                 /* fd is a tty at this point */
3978                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
3979                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3980                         close(ofd);
3981                 if (fd < 0)
3982                         goto out; /* F_DUPFD failed */
3983                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
3984                         close_on_exec_on(fd);
3985                 while (1) { /* while we are in the background */
3986                         pgrp = tcgetpgrp(fd);
3987                         if (pgrp < 0) {
3988  out:
3989                                 ash_msg("can't access tty; job control turned off");
3990                                 mflag = on = 0;
3991                                 goto close;
3992                         }
3993                         if (pgrp == getpgrp())
3994                                 break;
3995                         killpg(0, SIGTTIN);
3996                 }
3997                 initialpgrp = pgrp;
3998
3999                 setsignal(SIGTSTP);
4000                 setsignal(SIGTTOU);
4001                 setsignal(SIGTTIN);
4002                 pgrp = rootpid;
4003                 setpgid(0, pgrp);
4004                 xtcsetpgrp(fd, pgrp);
4005         } else {
4006                 /* turning job control off */
4007                 fd = ttyfd;
4008                 pgrp = initialpgrp;
4009                 /* was xtcsetpgrp, but this can make exiting ash
4010                  * loop forever if pty is already deleted */
4011                 tcsetpgrp(fd, pgrp);
4012                 setpgid(0, pgrp);
4013                 setsignal(SIGTSTP);
4014                 setsignal(SIGTTOU);
4015                 setsignal(SIGTTIN);
4016  close:
4017                 if (fd >= 0)
4018                         close(fd);
4019                 fd = -1;
4020         }
4021         ttyfd = fd;
4022         doing_jobctl = on;
4023 }
4024
4025 static int FAST_FUNC
4026 killcmd(int argc, char **argv)
4027 {
4028         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4029                 int i = 1;
4030                 do {
4031                         if (argv[i][0] == '%') {
4032                                 /*
4033                                  * "kill %N" - job kill
4034                                  * Converting to pgrp / pid kill
4035                                  */
4036                                 struct job *jp;
4037                                 char *dst;
4038                                 int j, n;
4039
4040                                 jp = getjob(argv[i], 0);
4041                                 /*
4042                                  * In jobs started under job control, we signal
4043                                  * entire process group by kill -PGRP_ID.
4044                                  * This happens, f.e., in interactive shell.
4045                                  *
4046                                  * Otherwise, we signal each child via
4047                                  * kill PID1 PID2 PID3.
4048                                  * Testcases:
4049                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4050                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4051                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4052                                  */
4053                                 n = jp->nprocs; /* can't be 0 (I hope) */
4054                                 if (jp->jobctl)
4055                                         n = 1;
4056                                 dst = alloca(n * sizeof(int)*4);
4057                                 argv[i] = dst;
4058                                 for (j = 0; j < n; j++) {
4059                                         struct procstat *ps = &jp->ps[j];
4060                                         /* Skip non-running and not-stopped members
4061                                          * (i.e. dead members) of the job
4062                                          */
4063                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4064                                                 continue;
4065                                         /*
4066                                          * kill_main has matching code to expect
4067                                          * leading space. Needed to not confuse
4068                                          * negative pids with "kill -SIGNAL_NO" syntax
4069                                          */
4070                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4071                                 }
4072                                 *dst = '\0';
4073                         }
4074                 } while (argv[++i]);
4075         }
4076         return kill_main(argc, argv);
4077 }
4078
4079 static void
4080 showpipe(struct job *jp /*, FILE *out*/)
4081 {
4082         struct procstat *ps;
4083         struct procstat *psend;
4084
4085         psend = jp->ps + jp->nprocs;
4086         for (ps = jp->ps + 1; ps < psend; ps++)
4087                 printf(" | %s", ps->ps_cmd);
4088         newline_and_flush(stdout);
4089         flush_stdout_stderr();
4090 }
4091
4092
4093 static int
4094 restartjob(struct job *jp, int mode)
4095 {
4096         struct procstat *ps;
4097         int i;
4098         int status;
4099         pid_t pgid;
4100
4101         INT_OFF;
4102         if (jp->state == JOBDONE)
4103                 goto out;
4104         jp->state = JOBRUNNING;
4105         pgid = jp->ps[0].ps_pid;
4106         if (mode == FORK_FG) {
4107                 get_tty_state();
4108                 xtcsetpgrp(ttyfd, pgid);
4109         }
4110         killpg(pgid, SIGCONT);
4111         ps = jp->ps;
4112         i = jp->nprocs;
4113         do {
4114                 if (WIFSTOPPED(ps->ps_status)) {
4115                         ps->ps_status = -1;
4116                 }
4117                 ps++;
4118         } while (--i);
4119  out:
4120         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4121         INT_ON;
4122         return status;
4123 }
4124
4125 static int FAST_FUNC
4126 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4127 {
4128         struct job *jp;
4129         int mode;
4130         int retval;
4131
4132         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4133         nextopt(nullstr);
4134         argv = argptr;
4135         do {
4136                 jp = getjob(*argv, 1);
4137                 if (mode == FORK_BG) {
4138                         set_curjob(jp, CUR_RUNNING);
4139                         printf("[%d] ", jobno(jp));
4140                 }
4141                 out1str(jp->ps[0].ps_cmd);
4142                 showpipe(jp /*, stdout*/);
4143                 retval = restartjob(jp, mode);
4144         } while (*argv && *++argv);
4145         return retval;
4146 }
4147 #endif
4148
4149 static int
4150 sprint_status48(char *s, int status, int sigonly)
4151 {
4152         int col;
4153         int st;
4154
4155         col = 0;
4156         if (!WIFEXITED(status)) {
4157 #if JOBS
4158                 if (WIFSTOPPED(status))
4159                         st = WSTOPSIG(status);
4160                 else
4161 #endif
4162                         st = WTERMSIG(status);
4163                 if (sigonly) {
4164                         if (st == SIGINT || st == SIGPIPE)
4165                                 goto out;
4166 #if JOBS
4167                         if (WIFSTOPPED(status))
4168                                 goto out;
4169 #endif
4170                 }
4171                 st &= 0x7f;
4172 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4173                 col = fmtstr(s, 32, strsignal(st));
4174                 if (WCOREDUMP(status)) {
4175                         strcpy(s + col, " (core dumped)");
4176                         col += sizeof(" (core dumped)")-1;
4177                 }
4178         } else if (!sigonly) {
4179                 st = WEXITSTATUS(status);
4180                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4181         }
4182  out:
4183         return col;
4184 }
4185
4186 static int
4187 wait_block_or_sig(int *status)
4188 {
4189         int pid;
4190
4191         do {
4192                 sigset_t mask;
4193
4194                 /* Poll all children for changes in their state */
4195                 got_sigchld = 0;
4196                 /* if job control is active, accept stopped processes too */
4197                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4198                 if (pid != 0)
4199                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4200
4201                 /* Children exist, but none are ready. Sleep until interesting signal */
4202 #if 1
4203                 sigfillset(&mask);
4204                 sigprocmask(SIG_SETMASK, &mask, &mask);
4205                 while (!got_sigchld && !pending_sig)
4206                         sigsuspend(&mask);
4207                 sigprocmask(SIG_SETMASK, &mask, NULL);
4208 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4209                 while (!got_sigchld && !pending_sig)
4210                         pause();
4211 #endif
4212
4213                 /* If it was SIGCHLD, poll children again */
4214         } while (got_sigchld);
4215
4216         return pid;
4217 }
4218
4219 #define DOWAIT_NONBLOCK 0
4220 #define DOWAIT_BLOCK    1
4221 #define DOWAIT_BLOCK_OR_SIG 2
4222
4223 static int
4224 dowait(int block, struct job *job)
4225 {
4226         int pid;
4227         int status;
4228         struct job *jp;
4229         struct job *thisjob = NULL;
4230
4231         TRACE(("dowait(0x%x) called\n", block));
4232
4233         /* It's wrong to call waitpid() outside of INT_OFF region:
4234          * signal can arrive just after syscall return and handler can
4235          * longjmp away, losing stop/exit notification processing.
4236          * Thus, for "jobs" builtin, and for waiting for a fg job,
4237          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4238          *
4239          * However, for "wait" builtin it is wrong to simply call waitpid()
4240          * in INT_OFF region: "wait" needs to wait for any running job
4241          * to change state, but should exit on any trap too.
4242          * In INT_OFF region, a signal just before syscall entry can set
4243          * pending_sig variables, but we can't check them, and we would
4244          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4245          *
4246          * Because of this, we run inside INT_OFF, but use a special routine
4247          * which combines waitpid() and sigsuspend().
4248          * This is the reason why we need to have a handler for SIGCHLD:
4249          * SIG_DFL handler does not wake sigsuspend().
4250          */
4251         INT_OFF;
4252         if (block == DOWAIT_BLOCK_OR_SIG) {
4253                 pid = wait_block_or_sig(&status);
4254         } else {
4255                 int wait_flags = 0;
4256                 if (block == DOWAIT_NONBLOCK)
4257                         wait_flags = WNOHANG;
4258                 /* if job control is active, accept stopped processes too */
4259                 if (doing_jobctl)
4260                         wait_flags |= WUNTRACED;
4261                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4262                 pid = waitpid(-1, &status, wait_flags);
4263         }
4264         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4265                                 pid, status, errno, strerror(errno)));
4266         if (pid <= 0)
4267                 goto out;
4268
4269         thisjob = NULL;
4270         for (jp = curjob; jp; jp = jp->prev_job) {
4271                 int jobstate;
4272                 struct procstat *ps;
4273                 struct procstat *psend;
4274                 if (jp->state == JOBDONE)
4275                         continue;
4276                 jobstate = JOBDONE;
4277                 ps = jp->ps;
4278                 psend = ps + jp->nprocs;
4279                 do {
4280                         if (ps->ps_pid == pid) {
4281                                 TRACE(("Job %d: changing status of proc %d "
4282                                         "from 0x%x to 0x%x\n",
4283                                         jobno(jp), pid, ps->ps_status, status));
4284                                 ps->ps_status = status;
4285                                 thisjob = jp;
4286                         }
4287                         if (ps->ps_status == -1)
4288                                 jobstate = JOBRUNNING;
4289 #if JOBS
4290                         if (jobstate == JOBRUNNING)
4291                                 continue;
4292                         if (WIFSTOPPED(ps->ps_status)) {
4293                                 jp->stopstatus = ps->ps_status;
4294                                 jobstate = JOBSTOPPED;
4295                         }
4296 #endif
4297                 } while (++ps < psend);
4298                 if (!thisjob)
4299                         continue;
4300
4301                 /* Found the job where one of its processes changed its state.
4302                  * Is there at least one live and running process in this job? */
4303                 if (jobstate != JOBRUNNING) {
4304                         /* No. All live processes in the job are stopped
4305                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4306                          */
4307                         thisjob->changed = 1;
4308                         if (thisjob->state != jobstate) {
4309                                 TRACE(("Job %d: changing state from %d to %d\n",
4310                                         jobno(thisjob), thisjob->state, jobstate));
4311                                 thisjob->state = jobstate;
4312 #if JOBS
4313                                 if (jobstate == JOBSTOPPED)
4314                                         set_curjob(thisjob, CUR_STOPPED);
4315 #endif
4316                         }
4317                 }
4318                 goto out;
4319         }
4320         /* The process wasn't found in job list */
4321 #if JOBS
4322         if (!WIFSTOPPED(status))
4323                 jobless--;
4324 #endif
4325  out:
4326         INT_ON;
4327
4328         if (thisjob && thisjob == job) {
4329                 char s[48 + 1];
4330                 int len;
4331
4332                 len = sprint_status48(s, status, 1);
4333                 if (len) {
4334                         s[len] = '\n';
4335                         s[len + 1] = '\0';
4336                         out2str(s);
4337                 }
4338         }
4339         return pid;
4340 }
4341
4342 #if JOBS
4343 static void
4344 showjob(struct job *jp, int mode)
4345 {
4346         struct procstat *ps;
4347         struct procstat *psend;
4348         int col;
4349         int indent_col;
4350         char s[16 + 16 + 48];
4351         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4352
4353         ps = jp->ps;
4354
4355         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4356                 /* just output process (group) id of pipeline */
4357                 fprintf(out, "%d\n", ps->ps_pid);
4358                 return;
4359         }
4360
4361         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4362         indent_col = col;
4363
4364         if (jp == curjob)
4365                 s[col - 3] = '+';
4366         else if (curjob && jp == curjob->prev_job)
4367                 s[col - 3] = '-';
4368
4369         if (mode & SHOW_PIDS)
4370                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4371
4372         psend = ps + jp->nprocs;
4373
4374         if (jp->state == JOBRUNNING) {
4375                 strcpy(s + col, "Running");
4376                 col += sizeof("Running") - 1;
4377         } else {
4378                 int status = psend[-1].ps_status;
4379                 if (jp->state == JOBSTOPPED)
4380                         status = jp->stopstatus;
4381                 col += sprint_status48(s + col, status, 0);
4382         }
4383         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4384
4385         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4386          * or prints several "PID             | <cmdN>" lines,
4387          * depending on SHOW_PIDS bit.
4388          * We do not print status of individual processes
4389          * between PID and <cmdN>. bash does it, but not very well:
4390          * first line shows overall job status, not process status,
4391          * making it impossible to know 1st process status.
4392          */
4393         goto start;
4394         do {
4395                 /* for each process */
4396                 s[0] = '\0';
4397                 col = 33;
4398                 if (mode & SHOW_PIDS)
4399                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4400  start:
4401                 fprintf(out, "%s%*c%s%s",
4402                                 s,
4403                                 33 - col >= 0 ? 33 - col : 0, ' ',
4404                                 ps == jp->ps ? "" : "| ",
4405                                 ps->ps_cmd
4406                 );
4407         } while (++ps != psend);
4408         newline_and_flush(out);
4409
4410         jp->changed = 0;
4411
4412         if (jp->state == JOBDONE) {
4413                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4414                 freejob(jp);
4415         }
4416 }
4417
4418 /*
4419  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4420  * statuses have changed since the last call to showjobs.
4421  */
4422 static void
4423 showjobs(int mode)
4424 {
4425         struct job *jp;
4426
4427         TRACE(("showjobs(0x%x) called\n", mode));
4428
4429         /* Handle all finished jobs */
4430         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4431                 continue;
4432
4433         for (jp = curjob; jp; jp = jp->prev_job) {
4434                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4435                         showjob(jp, mode);
4436                 }
4437         }
4438 }
4439
4440 static int FAST_FUNC
4441 jobscmd(int argc UNUSED_PARAM, char **argv)
4442 {
4443         int mode, m;
4444
4445         mode = 0;
4446         while ((m = nextopt("lp")) != '\0') {
4447                 if (m == 'l')
4448                         mode |= SHOW_PIDS;
4449                 else
4450                         mode |= SHOW_ONLY_PGID;
4451         }
4452
4453         argv = argptr;
4454         if (*argv) {
4455                 do
4456                         showjob(getjob(*argv, 0), mode);
4457                 while (*++argv);
4458         } else {
4459                 showjobs(mode);
4460         }
4461
4462         return 0;
4463 }
4464 #endif /* JOBS */
4465
4466 /* Called only on finished or stopped jobs (no members are running) */
4467 static int
4468 getstatus(struct job *job)
4469 {
4470         int status;
4471         int retval;
4472         struct procstat *ps;
4473
4474         /* Fetch last member's status */
4475         ps = job->ps + job->nprocs - 1;
4476         status = ps->ps_status;
4477         if (pipefail) {
4478                 /* "set -o pipefail" mode: use last _nonzero_ status */
4479                 while (status == 0 && --ps >= job->ps)
4480                         status = ps->ps_status;
4481         }
4482
4483         retval = WEXITSTATUS(status);
4484         if (!WIFEXITED(status)) {
4485 #if JOBS
4486                 retval = WSTOPSIG(status);
4487                 if (!WIFSTOPPED(status))
4488 #endif
4489                 {
4490                         /* XXX: limits number of signals */
4491                         retval = WTERMSIG(status);
4492 #if JOBS
4493                         if (retval == SIGINT)
4494                                 job->sigint = 1;
4495 #endif
4496                 }
4497                 retval += 128;
4498         }
4499         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4500                 jobno(job), job->nprocs, status, retval));
4501         return retval;
4502 }
4503
4504 static int FAST_FUNC
4505 waitcmd(int argc UNUSED_PARAM, char **argv)
4506 {
4507         struct job *job;
4508         int retval;
4509         struct job *jp;
4510
4511         nextopt(nullstr);
4512         retval = 0;
4513
4514         argv = argptr;
4515         if (!*argv) {
4516                 /* wait for all jobs */
4517                 for (;;) {
4518                         jp = curjob;
4519                         while (1) {
4520                                 if (!jp) /* no running procs */
4521                                         goto ret;
4522                                 if (jp->state == JOBRUNNING)
4523                                         break;
4524                                 jp->waited = 1;
4525                                 jp = jp->prev_job;
4526                         }
4527         /* man bash:
4528          * "When bash is waiting for an asynchronous command via
4529          * the wait builtin, the reception of a signal for which a trap
4530          * has been set will cause the wait builtin to return immediately
4531          * with an exit status greater than 128, immediately after which
4532          * the trap is executed."
4533          */
4534                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4535         /* if child sends us a signal *and immediately exits*,
4536          * dowait() returns pid > 0. Check this case,
4537          * not "if (dowait() < 0)"!
4538          */
4539                         if (pending_sig)
4540                                 goto sigout;
4541                 }
4542         }
4543
4544         retval = 127;
4545         do {
4546                 if (**argv != '%') {
4547                         pid_t pid = number(*argv);
4548                         job = curjob;
4549                         while (1) {
4550                                 if (!job)
4551                                         goto repeat;
4552                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4553                                         break;
4554                                 job = job->prev_job;
4555                         }
4556                 } else {
4557                         job = getjob(*argv, 0);
4558                 }
4559                 /* loop until process terminated or stopped */
4560                 while (job->state == JOBRUNNING) {
4561                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4562                         if (pending_sig)
4563                                 goto sigout;
4564                 }
4565                 job->waited = 1;
4566                 retval = getstatus(job);
4567  repeat: ;
4568         } while (*++argv);
4569
4570  ret:
4571         return retval;
4572  sigout:
4573         retval = 128 + pending_sig;
4574         return retval;
4575 }
4576
4577 static struct job *
4578 growjobtab(void)
4579 {
4580         size_t len;
4581         ptrdiff_t offset;
4582         struct job *jp, *jq;
4583
4584         len = njobs * sizeof(*jp);
4585         jq = jobtab;
4586         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4587
4588         offset = (char *)jp - (char *)jq;
4589         if (offset) {
4590                 /* Relocate pointers */
4591                 size_t l = len;
4592
4593                 jq = (struct job *)((char *)jq + l);
4594                 while (l) {
4595                         l -= sizeof(*jp);
4596                         jq--;
4597 #define joff(p) ((struct job *)((char *)(p) + l))
4598 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4599                         if (joff(jp)->ps == &jq->ps0)
4600                                 jmove(joff(jp)->ps);
4601                         if (joff(jp)->prev_job)
4602                                 jmove(joff(jp)->prev_job);
4603                 }
4604                 if (curjob)
4605                         jmove(curjob);
4606 #undef joff
4607 #undef jmove
4608         }
4609
4610         njobs += 4;
4611         jobtab = jp;
4612         jp = (struct job *)((char *)jp + len);
4613         jq = jp + 3;
4614         do {
4615                 jq->used = 0;
4616         } while (--jq >= jp);
4617         return jp;
4618 }
4619
4620 /*
4621  * Return a new job structure.
4622  * Called with interrupts off.
4623  */
4624 static struct job *
4625 makejob(/*union node *node,*/ int nprocs)
4626 {
4627         int i;
4628         struct job *jp;
4629
4630         for (i = njobs, jp = jobtab; ; jp++) {
4631                 if (--i < 0) {
4632                         jp = growjobtab();
4633                         break;
4634                 }
4635                 if (jp->used == 0)
4636                         break;
4637                 if (jp->state != JOBDONE || !jp->waited)
4638                         continue;
4639 #if JOBS
4640                 if (doing_jobctl)
4641                         continue;
4642 #endif
4643                 freejob(jp);
4644                 break;
4645         }
4646         memset(jp, 0, sizeof(*jp));
4647 #if JOBS
4648         /* jp->jobctl is a bitfield.
4649          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4650         if (doing_jobctl)
4651                 jp->jobctl = 1;
4652 #endif
4653         jp->prev_job = curjob;
4654         curjob = jp;
4655         jp->used = 1;
4656         jp->ps = &jp->ps0;
4657         if (nprocs > 1) {
4658                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4659         }
4660         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4661                                 jobno(jp)));
4662         return jp;
4663 }
4664
4665 #if JOBS
4666 /*
4667  * Return a string identifying a command (to be printed by the
4668  * jobs command).
4669  */
4670 static char *cmdnextc;
4671
4672 static void
4673 cmdputs(const char *s)
4674 {
4675         static const char vstype[VSTYPE + 1][3] = {
4676                 "", "}", "-", "+", "?", "=",
4677                 "%", "%%", "#", "##"
4678                 IF_BASH_SUBSTR(, ":")
4679                 IF_BASH_PATTERN_SUBST(, "/", "//")
4680         };
4681
4682         const char *p, *str;
4683         char cc[2];
4684         char *nextc;
4685         unsigned char c;
4686         unsigned char subtype = 0;
4687         int quoted = 0;
4688
4689         cc[1] = '\0';
4690         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4691         p = s;
4692         while ((c = *p++) != '\0') {
4693                 str = NULL;
4694                 switch (c) {
4695                 case CTLESC:
4696                         c = *p++;
4697                         break;
4698                 case CTLVAR:
4699                         subtype = *p++;
4700                         if ((subtype & VSTYPE) == VSLENGTH)
4701                                 str = "${#";
4702                         else
4703                                 str = "${";
4704                         goto dostr;
4705                 case CTLENDVAR:
4706                         str = "\"}" + !(quoted & 1);
4707                         quoted >>= 1;
4708                         subtype = 0;
4709                         goto dostr;
4710                 case CTLBACKQ:
4711                         str = "$(...)";
4712                         goto dostr;
4713 #if ENABLE_FEATURE_SH_MATH
4714                 case CTLARI:
4715                         str = "$((";
4716                         goto dostr;
4717                 case CTLENDARI:
4718                         str = "))";
4719                         goto dostr;
4720 #endif
4721                 case CTLQUOTEMARK:
4722                         quoted ^= 1;
4723                         c = '"';
4724                         break;
4725                 case '=':
4726                         if (subtype == 0)
4727                                 break;
4728                         if ((subtype & VSTYPE) != VSNORMAL)
4729                                 quoted <<= 1;
4730                         str = vstype[subtype & VSTYPE];
4731                         if (subtype & VSNUL)
4732                                 c = ':';
4733                         else
4734                                 goto checkstr;
4735                         break;
4736                 case '\'':
4737                 case '\\':
4738                 case '"':
4739                 case '$':
4740                         /* These can only happen inside quotes */
4741                         cc[0] = c;
4742                         str = cc;
4743 //FIXME:
4744 // $ true $$ &
4745 // $ <cr>
4746 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4747                         c = '\\';
4748                         break;
4749                 default:
4750                         break;
4751                 }
4752                 USTPUTC(c, nextc);
4753  checkstr:
4754                 if (!str)
4755                         continue;
4756  dostr:
4757                 while ((c = *str++) != '\0') {
4758                         USTPUTC(c, nextc);
4759                 }
4760         } /* while *p++ not NUL */
4761
4762         if (quoted & 1) {
4763                 USTPUTC('"', nextc);
4764         }
4765         *nextc = 0;
4766         cmdnextc = nextc;
4767 }
4768
4769 /* cmdtxt() and cmdlist() call each other */
4770 static void cmdtxt(union node *n);
4771
4772 static void
4773 cmdlist(union node *np, int sep)
4774 {
4775         for (; np; np = np->narg.next) {
4776                 if (!sep)
4777                         cmdputs(" ");
4778                 cmdtxt(np);
4779                 if (sep && np->narg.next)
4780                         cmdputs(" ");
4781         }
4782 }
4783
4784 static void
4785 cmdtxt(union node *n)
4786 {
4787         union node *np;
4788         struct nodelist *lp;
4789         const char *p;
4790
4791         if (!n)
4792                 return;
4793         switch (n->type) {
4794         default:
4795 #if DEBUG
4796                 abort();
4797 #endif
4798         case NPIPE:
4799                 lp = n->npipe.cmdlist;
4800                 for (;;) {
4801                         cmdtxt(lp->n);
4802                         lp = lp->next;
4803                         if (!lp)
4804                                 break;
4805                         cmdputs(" | ");
4806                 }
4807                 break;
4808         case NSEMI:
4809                 p = "; ";
4810                 goto binop;
4811         case NAND:
4812                 p = " && ";
4813                 goto binop;
4814         case NOR:
4815                 p = " || ";
4816  binop:
4817                 cmdtxt(n->nbinary.ch1);
4818                 cmdputs(p);
4819                 n = n->nbinary.ch2;
4820                 goto donode;
4821         case NREDIR:
4822         case NBACKGND:
4823                 n = n->nredir.n;
4824                 goto donode;
4825         case NNOT:
4826                 cmdputs("!");
4827                 n = n->nnot.com;
4828  donode:
4829                 cmdtxt(n);
4830                 break;
4831         case NIF:
4832                 cmdputs("if ");
4833                 cmdtxt(n->nif.test);
4834                 cmdputs("; then ");
4835                 if (n->nif.elsepart) {
4836                         cmdtxt(n->nif.ifpart);
4837                         cmdputs("; else ");
4838                         n = n->nif.elsepart;
4839                 } else {
4840                         n = n->nif.ifpart;
4841                 }
4842                 p = "; fi";
4843                 goto dotail;
4844         case NSUBSHELL:
4845                 cmdputs("(");
4846                 n = n->nredir.n;
4847                 p = ")";
4848                 goto dotail;
4849         case NWHILE:
4850                 p = "while ";
4851                 goto until;
4852         case NUNTIL:
4853                 p = "until ";
4854  until:
4855                 cmdputs(p);
4856                 cmdtxt(n->nbinary.ch1);
4857                 n = n->nbinary.ch2;
4858                 p = "; done";
4859  dodo:
4860                 cmdputs("; do ");
4861  dotail:
4862                 cmdtxt(n);
4863                 goto dotail2;
4864         case NFOR:
4865                 cmdputs("for ");
4866                 cmdputs(n->nfor.var);
4867                 cmdputs(" in ");
4868                 cmdlist(n->nfor.args, 1);
4869                 n = n->nfor.body;
4870                 p = "; done";
4871                 goto dodo;
4872         case NDEFUN:
4873                 cmdputs(n->ndefun.text);
4874                 p = "() { ... }";
4875                 goto dotail2;
4876         case NCMD:
4877                 cmdlist(n->ncmd.args, 1);
4878                 cmdlist(n->ncmd.redirect, 0);
4879                 break;
4880         case NARG:
4881                 p = n->narg.text;
4882  dotail2:
4883                 cmdputs(p);
4884                 break;
4885         case NHERE:
4886         case NXHERE:
4887                 p = "<<...";
4888                 goto dotail2;
4889         case NCASE:
4890                 cmdputs("case ");
4891                 cmdputs(n->ncase.expr->narg.text);
4892                 cmdputs(" in ");
4893                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4894                         cmdtxt(np->nclist.pattern);
4895                         cmdputs(") ");
4896                         cmdtxt(np->nclist.body);
4897                         cmdputs(";; ");
4898                 }
4899                 p = "esac";
4900                 goto dotail2;
4901         case NTO:
4902                 p = ">";
4903                 goto redir;
4904         case NCLOBBER:
4905                 p = ">|";
4906                 goto redir;
4907         case NAPPEND:
4908                 p = ">>";
4909                 goto redir;
4910 #if BASH_REDIR_OUTPUT
4911         case NTO2:
4912 #endif
4913         case NTOFD:
4914                 p = ">&";
4915                 goto redir;
4916         case NFROM:
4917                 p = "<";
4918                 goto redir;
4919         case NFROMFD:
4920                 p = "<&";
4921                 goto redir;
4922         case NFROMTO:
4923                 p = "<>";
4924  redir:
4925                 cmdputs(utoa(n->nfile.fd));
4926                 cmdputs(p);
4927                 if (n->type == NTOFD || n->type == NFROMFD) {
4928                         if (n->ndup.dupfd >= 0)
4929                                 cmdputs(utoa(n->ndup.dupfd));
4930                         else
4931                                 cmdputs("-");
4932                         break;
4933                 }
4934                 n = n->nfile.fname;
4935                 goto donode;
4936         }
4937 }
4938
4939 static char *
4940 commandtext(union node *n)
4941 {
4942         char *name;
4943
4944         STARTSTACKSTR(cmdnextc);
4945         cmdtxt(n);
4946         name = stackblock();
4947         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4948         return ckstrdup(name);
4949 }
4950 #endif /* JOBS */
4951
4952 /*
4953  * Fork off a subshell.  If we are doing job control, give the subshell its
4954  * own process group.  Jp is a job structure that the job is to be added to.
4955  * N is the command that will be evaluated by the child.  Both jp and n may
4956  * be NULL.  The mode parameter can be one of the following:
4957  *      FORK_FG - Fork off a foreground process.
4958  *      FORK_BG - Fork off a background process.
4959  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4960  *                   process group even if job control is on.
4961  *
4962  * When job control is turned off, background processes have their standard
4963  * input redirected to /dev/null (except for the second and later processes
4964  * in a pipeline).
4965  *
4966  * Called with interrupts off.
4967  */
4968 /*
4969  * Clear traps on a fork.
4970  */
4971 static void
4972 clear_traps(void)
4973 {
4974         char **tp;
4975
4976         INT_OFF;
4977         for (tp = trap; tp < &trap[NSIG]; tp++) {
4978                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4979                         if (trap_ptr == trap)
4980                                 free(*tp);
4981                         /* else: it "belongs" to trap_ptr vector, don't free */
4982                         *tp = NULL;
4983                         if ((tp - trap) != 0)
4984                                 setsignal(tp - trap);
4985                 }
4986         }
4987         may_have_traps = 0;
4988         INT_ON;
4989 }
4990
4991 /* Lives far away from here, needed for forkchild */
4992 static void closescript(void);
4993
4994 /* Called after fork(), in child */
4995 /* jp and n are NULL when called by openhere() for heredoc support */
4996 static NOINLINE void
4997 forkchild(struct job *jp, union node *n, int mode)
4998 {
4999         int oldlvl;
5000
5001         TRACE(("Child shell %d\n", getpid()));
5002         oldlvl = shlvl;
5003         shlvl++;
5004
5005         /* man bash: "Non-builtin commands run by bash have signal handlers
5006          * set to the values inherited by the shell from its parent".
5007          * Do we do it correctly? */
5008
5009         closescript();
5010
5011         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5012          && n && n->type == NCMD        /* is it single cmd? */
5013         /* && n->ncmd.args->type == NARG - always true? */
5014          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5015          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5016         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5017         ) {
5018                 TRACE(("Trap hack\n"));
5019                 /* Awful hack for `trap` or $(trap).
5020                  *
5021                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5022                  * contains an example where "trap" is executed in a subshell:
5023                  *
5024                  * save_traps=$(trap)
5025                  * ...
5026                  * eval "$save_traps"
5027                  *
5028                  * Standard does not say that "trap" in subshell shall print
5029                  * parent shell's traps. It only says that its output
5030                  * must have suitable form, but then, in the above example
5031                  * (which is not supposed to be normative), it implies that.
5032                  *
5033                  * bash (and probably other shell) does implement it
5034                  * (traps are reset to defaults, but "trap" still shows them),
5035                  * but as a result, "trap" logic is hopelessly messed up:
5036                  *
5037                  * # trap
5038                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5039                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5040                  * # true | trap   <--- trap is in subshell - no output (ditto)
5041                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5042                  * trap -- 'echo Ho' SIGWINCH
5043                  * # echo `(trap)`         <--- in subshell in subshell - output
5044                  * trap -- 'echo Ho' SIGWINCH
5045                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5046                  * trap -- 'echo Ho' SIGWINCH
5047                  *
5048                  * The rules when to forget and when to not forget traps
5049                  * get really complex and nonsensical.
5050                  *
5051                  * Our solution: ONLY bare $(trap) or `trap` is special.
5052                  */
5053                 /* Save trap handler strings for trap builtin to print */
5054                 trap_ptr = xmemdup(trap, sizeof(trap));
5055                 /* Fall through into clearing traps */
5056         }
5057         clear_traps();
5058 #if JOBS
5059         /* do job control only in root shell */
5060         doing_jobctl = 0;
5061         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5062                 pid_t pgrp;
5063
5064                 if (jp->nprocs == 0)
5065                         pgrp = getpid();
5066                 else
5067                         pgrp = jp->ps[0].ps_pid;
5068                 /* this can fail because we are doing it in the parent also */
5069                 setpgid(0, pgrp);
5070                 if (mode == FORK_FG)
5071                         xtcsetpgrp(ttyfd, pgrp);
5072                 setsignal(SIGTSTP);
5073                 setsignal(SIGTTOU);
5074         } else
5075 #endif
5076         if (mode == FORK_BG) {
5077                 /* man bash: "When job control is not in effect,
5078                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5079                 ignoresig(SIGINT);
5080                 ignoresig(SIGQUIT);
5081                 if (jp->nprocs == 0) {
5082                         close(0);
5083                         if (open(bb_dev_null, O_RDONLY) != 0)
5084                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5085                 }
5086         }
5087         if (oldlvl == 0) {
5088                 if (iflag) { /* why if iflag only? */
5089                         setsignal(SIGINT);
5090                         setsignal(SIGTERM);
5091                 }
5092                 /* man bash:
5093                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5094                  * commands run by bash have signal handlers
5095                  * set to the values inherited by the shell
5096                  * from its parent".
5097                  * Take care of the second rule: */
5098                 setsignal(SIGQUIT);
5099         }
5100 #if JOBS
5101         if (n && n->type == NCMD
5102          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5103         ) {
5104                 TRACE(("Job hack\n"));
5105                 /* "jobs": we do not want to clear job list for it,
5106                  * instead we remove only _its_ own_ job from job list.
5107                  * This makes "jobs .... | cat" more useful.
5108                  */
5109                 freejob(curjob);
5110                 return;
5111         }
5112 #endif
5113         for (jp = curjob; jp; jp = jp->prev_job)
5114                 freejob(jp);
5115         jobless = 0;
5116 }
5117
5118 /* Called after fork(), in parent */
5119 #if !JOBS
5120 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5121 #endif
5122 static void
5123 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5124 {
5125         TRACE(("In parent shell: child = %d\n", pid));
5126         if (!jp) {
5127                 /* jp is NULL when called by openhere() for heredoc support */
5128                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5129                         continue;
5130                 jobless++;
5131                 return;
5132         }
5133 #if JOBS
5134         if (mode != FORK_NOJOB && jp->jobctl) {
5135                 int pgrp;
5136
5137                 if (jp->nprocs == 0)
5138                         pgrp = pid;
5139                 else
5140                         pgrp = jp->ps[0].ps_pid;
5141                 /* This can fail because we are doing it in the child also */
5142                 setpgid(pid, pgrp);
5143         }
5144 #endif
5145         if (mode == FORK_BG) {
5146                 backgndpid = pid;               /* set $! */
5147                 set_curjob(jp, CUR_RUNNING);
5148         }
5149         if (jp) {
5150                 struct procstat *ps = &jp->ps[jp->nprocs++];
5151                 ps->ps_pid = pid;
5152                 ps->ps_status = -1;
5153                 ps->ps_cmd = nullstr;
5154 #if JOBS
5155                 if (doing_jobctl && n)
5156                         ps->ps_cmd = commandtext(n);
5157 #endif
5158         }
5159 }
5160
5161 /* jp and n are NULL when called by openhere() for heredoc support */
5162 static int
5163 forkshell(struct job *jp, union node *n, int mode)
5164 {
5165         int pid;
5166
5167         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5168         pid = fork();
5169         if (pid < 0) {
5170                 TRACE(("Fork failed, errno=%d", errno));
5171                 if (jp)
5172                         freejob(jp);
5173                 ash_msg_and_raise_perror("can't fork");
5174         }
5175         if (pid == 0) {
5176                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5177                 forkchild(jp, n, mode);
5178         } else {
5179                 forkparent(jp, n, mode, pid);
5180         }
5181         return pid;
5182 }
5183
5184 /*
5185  * Wait for job to finish.
5186  *
5187  * Under job control we have the problem that while a child process
5188  * is running interrupts generated by the user are sent to the child
5189  * but not to the shell.  This means that an infinite loop started by
5190  * an interactive user may be hard to kill.  With job control turned off,
5191  * an interactive user may place an interactive program inside a loop.
5192  * If the interactive program catches interrupts, the user doesn't want
5193  * these interrupts to also abort the loop.  The approach we take here
5194  * is to have the shell ignore interrupt signals while waiting for a
5195  * foreground process to terminate, and then send itself an interrupt
5196  * signal if the child process was terminated by an interrupt signal.
5197  * Unfortunately, some programs want to do a bit of cleanup and then
5198  * exit on interrupt; unless these processes terminate themselves by
5199  * sending a signal to themselves (instead of calling exit) they will
5200  * confuse this approach.
5201  *
5202  * Called with interrupts off.
5203  */
5204 static int
5205 waitforjob(struct job *jp)
5206 {
5207         int st;
5208
5209         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5210
5211         INT_OFF;
5212         while (jp->state == JOBRUNNING) {
5213                 /* In non-interactive shells, we _can_ get
5214                  * a keyboard signal here and be EINTRed,
5215                  * but we just loop back, waiting for command to complete.
5216                  *
5217                  * man bash:
5218                  * "If bash is waiting for a command to complete and receives
5219                  * a signal for which a trap has been set, the trap
5220                  * will not be executed until the command completes."
5221                  *
5222                  * Reality is that even if trap is not set, bash
5223                  * will not act on the signal until command completes.
5224                  * Try this. sleep5intoff.c:
5225                  * #include <signal.h>
5226                  * #include <unistd.h>
5227                  * int main() {
5228                  *         sigset_t set;
5229                  *         sigemptyset(&set);
5230                  *         sigaddset(&set, SIGINT);
5231                  *         sigaddset(&set, SIGQUIT);
5232                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5233                  *         sleep(5);
5234                  *         return 0;
5235                  * }
5236                  * $ bash -c './sleep5intoff; echo hi'
5237                  * ^C^C^C^C <--- pressing ^C once a second
5238                  * $ _
5239                  * $ bash -c './sleep5intoff; echo hi'
5240                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5241                  * $ _
5242                  */
5243                 dowait(DOWAIT_BLOCK, jp);
5244         }
5245         INT_ON;
5246
5247         st = getstatus(jp);
5248 #if JOBS
5249         if (jp->jobctl) {
5250                 xtcsetpgrp(ttyfd, rootpid);
5251                 restore_tty_if_stopped_or_signaled(jp);
5252
5253                 /*
5254                  * This is truly gross.
5255                  * If we're doing job control, then we did a TIOCSPGRP which
5256                  * caused us (the shell) to no longer be in the controlling
5257                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5258                  * intuit from the subprocess exit status whether a SIGINT
5259                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5260                  */
5261                 if (jp->sigint) /* TODO: do the same with all signals */
5262                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5263         }
5264         if (jp->state == JOBDONE)
5265 #endif
5266                 freejob(jp);
5267         return st;
5268 }
5269
5270 /*
5271  * return 1 if there are stopped jobs, otherwise 0
5272  */
5273 static int
5274 stoppedjobs(void)
5275 {
5276         struct job *jp;
5277         int retval;
5278
5279         retval = 0;
5280         if (job_warning)
5281                 goto out;
5282         jp = curjob;
5283         if (jp && jp->state == JOBSTOPPED) {
5284                 out2str("You have stopped jobs.\n");
5285                 job_warning = 2;
5286                 retval++;
5287         }
5288  out:
5289         return retval;
5290 }
5291
5292
5293 /*
5294  * Code for dealing with input/output redirection.
5295  */
5296
5297 #undef EMPTY
5298 #undef CLOSED
5299 #define EMPTY -2                /* marks an unused slot in redirtab */
5300 #define CLOSED -1               /* marks a slot of previously-closed fd */
5301
5302 /*
5303  * Handle here documents.  Normally we fork off a process to write the
5304  * data to a pipe.  If the document is short, we can stuff the data in
5305  * the pipe without forking.
5306  */
5307 /* openhere needs this forward reference */
5308 static void expandhere(union node *arg, int fd);
5309 static int
5310 openhere(union node *redir)
5311 {
5312         int pip[2];
5313         size_t len = 0;
5314
5315         if (pipe(pip) < 0)
5316                 ash_msg_and_raise_perror("can't create pipe");
5317         if (redir->type == NHERE) {
5318                 len = strlen(redir->nhere.doc->narg.text);
5319                 if (len <= PIPE_BUF) {
5320                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5321                         goto out;
5322                 }
5323         }
5324         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5325                 /* child */
5326                 close(pip[0]);
5327                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5328                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5329                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5330                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5331                 signal(SIGPIPE, SIG_DFL);
5332                 if (redir->type == NHERE)
5333                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5334                 else /* NXHERE */
5335                         expandhere(redir->nhere.doc, pip[1]);
5336                 _exit(EXIT_SUCCESS);
5337         }
5338  out:
5339         close(pip[1]);
5340         return pip[0];
5341 }
5342
5343 static int
5344 openredirect(union node *redir)
5345 {
5346         struct stat sb;
5347         char *fname;
5348         int f;
5349
5350         switch (redir->nfile.type) {
5351 /* Can't happen, our single caller does this itself */
5352 //      case NTOFD:
5353 //      case NFROMFD:
5354 //              return -1;
5355         case NHERE:
5356         case NXHERE:
5357                 return openhere(redir);
5358         }
5359
5360         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5361          * allocated space. Do it only when we know it is safe.
5362          */
5363         fname = redir->nfile.expfname;
5364
5365         switch (redir->nfile.type) {
5366         default:
5367 #if DEBUG
5368                 abort();
5369 #endif
5370         case NFROM:
5371                 f = open(fname, O_RDONLY);
5372                 if (f < 0)
5373                         goto eopen;
5374                 break;
5375         case NFROMTO:
5376                 f = open(fname, O_RDWR|O_CREAT, 0666);
5377                 if (f < 0)
5378                         goto ecreate;
5379                 break;
5380         case NTO:
5381 #if BASH_REDIR_OUTPUT
5382         case NTO2:
5383 #endif
5384                 /* Take care of noclobber mode. */
5385                 if (Cflag) {
5386                         if (stat(fname, &sb) < 0) {
5387                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5388                                 if (f < 0)
5389                                         goto ecreate;
5390                         } else if (!S_ISREG(sb.st_mode)) {
5391                                 f = open(fname, O_WRONLY, 0666);
5392                                 if (f < 0)
5393                                         goto ecreate;
5394                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5395                                         close(f);
5396                                         errno = EEXIST;
5397                                         goto ecreate;
5398                                 }
5399                         } else {
5400                                 errno = EEXIST;
5401                                 goto ecreate;
5402                         }
5403                         break;
5404                 }
5405                 /* FALLTHROUGH */
5406         case NCLOBBER:
5407                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5408                 if (f < 0)
5409                         goto ecreate;
5410                 break;
5411         case NAPPEND:
5412                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5413                 if (f < 0)
5414                         goto ecreate;
5415                 break;
5416         }
5417
5418         return f;
5419  ecreate:
5420         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5421  eopen:
5422         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5423 }
5424
5425 /*
5426  * Copy a file descriptor to be >= 10. Throws exception on error.
5427  */
5428 static int
5429 savefd(int from)
5430 {
5431         int newfd;
5432         int err;
5433
5434         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5435         err = newfd < 0 ? errno : 0;
5436         if (err != EBADF) {
5437                 if (err)
5438                         ash_msg_and_raise_perror("%d", from);
5439                 close(from);
5440                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5441                         close_on_exec_on(newfd);
5442         }
5443
5444         return newfd;
5445 }
5446 static int
5447 dup2_or_raise(int from, int to)
5448 {
5449         int newfd;
5450
5451         newfd = (from != to) ? dup2(from, to) : to;
5452         if (newfd < 0) {
5453                 /* Happens when source fd is not open: try "echo >&99" */
5454                 ash_msg_and_raise_perror("%d", from);
5455         }
5456         return newfd;
5457 }
5458 static int
5459 dup_CLOEXEC(int fd, int avoid_fd)
5460 {
5461         int newfd;
5462  repeat:
5463         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5464         if (newfd >= 0) {
5465                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5466                         close_on_exec_on(newfd);
5467         } else { /* newfd < 0 */
5468                 if (errno == EBUSY)
5469                         goto repeat;
5470                 if (errno == EINTR)
5471                         goto repeat;
5472         }
5473         return newfd;
5474 }
5475 static int
5476 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5477 {
5478         int newfd;
5479  repeat:
5480         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5481         if (newfd < 0) {
5482                 if (errno == EBUSY)
5483                         goto repeat;
5484                 if (errno == EINTR)
5485                         goto repeat;
5486                 /* fd was not open? */
5487                 if (errno == EBADF)
5488                         return fd;
5489                 ash_msg_and_raise_perror("%d", newfd);
5490         }
5491         if (F_DUPFD_CLOEXEC == F_DUPFD)
5492                 close_on_exec_on(newfd);
5493         close(fd);
5494         return newfd;
5495 }
5496
5497 /* Struct def and variable are moved down to the first usage site */
5498 struct squirrel {
5499         int orig_fd;
5500         int moved_to;
5501 };
5502 struct redirtab {
5503         struct redirtab *next;
5504         int pair_count;
5505         struct squirrel two_fd[];
5506 };
5507 #define redirlist (G_var.redirlist)
5508
5509 static void
5510 add_squirrel_closed(struct redirtab *sq, int fd)
5511 {
5512         int i;
5513
5514         if (!sq)
5515                 return;
5516
5517         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5518                 /* If we collide with an already moved fd... */
5519                 if (fd == sq->two_fd[i].orig_fd) {
5520                         /* Examples:
5521                          * "echo 3>FILE 3>&- 3>FILE"
5522                          * "echo 3>&- 3>FILE"
5523                          * No need for last redirect to insert
5524                          * another "need to close 3" indicator.
5525                          */
5526                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5527                         return;
5528                 }
5529         }
5530         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5531         sq->two_fd[i].orig_fd = fd;
5532         sq->two_fd[i].moved_to = CLOSED;
5533 }
5534
5535 static int
5536 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5537 {
5538         int i, new_fd;
5539
5540         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5541                 avoid_fd = 9;
5542
5543 #if JOBS
5544         if (fd == ttyfd) {
5545                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5546                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5547                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5548                 return 1; /* "we closed fd" */
5549         }
5550 #endif
5551         /* Are we called from redirect(0)? E.g. redirect
5552          * in a forked child. No need to save fds,
5553          * we aren't going to use them anymore, ok to trash.
5554          */
5555         if (!sq)
5556                 return 0;
5557
5558         /* If this one of script's fds? */
5559         if (fd != 0) {
5560                 struct parsefile *pf = g_parsefile;
5561                 while (pf) {
5562                         /* We skip fd == 0 case because of the following:
5563                          * $ ash  # running ash interactively
5564                          * $ . ./script.sh
5565                          * and in script.sh: "exec 9>&0".
5566                          * Even though top-level pf_fd _is_ 0,
5567                          * it's still ok to use it: "read" builtin uses it,
5568                          * why should we cripple "exec" builtin?
5569                          */
5570                         if (fd == pf->pf_fd) {
5571                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5572                                 return 1; /* "we closed fd" */
5573                         }
5574                         pf = pf->prev;
5575                 }
5576         }
5577
5578         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5579
5580         /* First: do we collide with some already moved fds? */
5581         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5582                 /* If we collide with an already moved fd... */
5583                 if (fd == sq->two_fd[i].moved_to) {
5584                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5585                         sq->two_fd[i].moved_to = new_fd;
5586                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5587                         if (new_fd < 0) /* what? */
5588                                 xfunc_die();
5589                         return 0; /* "we did not close fd" */
5590                 }
5591                 if (fd == sq->two_fd[i].orig_fd) {
5592                         /* Example: echo Hello >/dev/null 1>&2 */
5593                         TRACE(("redirect_fd %d: already moved\n", fd));
5594                         return 0; /* "we did not close fd" */
5595                 }
5596         }
5597
5598         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5599         new_fd = dup_CLOEXEC(fd, avoid_fd);
5600         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5601         if (new_fd < 0) {
5602                 if (errno != EBADF)
5603                         xfunc_die();
5604                 /* new_fd = CLOSED; - already is -1 */
5605         }
5606         sq->two_fd[i].moved_to = new_fd;
5607         sq->two_fd[i].orig_fd = fd;
5608
5609         /* if we move stderr, let "set -x" code know */
5610         if (fd == preverrout_fd)
5611                 preverrout_fd = new_fd;
5612
5613         return 0; /* "we did not close fd" */
5614 }
5615
5616 static int
5617 internally_opened_fd(int fd, struct redirtab *sq)
5618 {
5619         int i;
5620 #if JOBS
5621         if (fd == ttyfd)
5622                 return 1;
5623 #endif
5624         /* If this one of script's fds? */
5625         if (fd != 0) {
5626                 struct parsefile *pf = g_parsefile;
5627                 while (pf) {
5628                         if (fd == pf->pf_fd)
5629                                 return 1;
5630                         pf = pf->prev;
5631                 }
5632         }
5633
5634         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5635                 if (fd == sq->two_fd[i].moved_to)
5636                         return 1;
5637         }
5638         return 0;
5639 }
5640
5641 /*
5642  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5643  * old file descriptors are stashed away so that the redirection can be
5644  * undone by calling popredir.
5645  */
5646 /* flags passed to redirect */
5647 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5648 static void
5649 redirect(union node *redir, int flags)
5650 {
5651         struct redirtab *sv;
5652
5653         if (!redir)
5654                 return;
5655
5656         sv = NULL;
5657         INT_OFF;
5658         if (flags & REDIR_PUSH)
5659                 sv = redirlist;
5660         do {
5661                 int fd;
5662                 int newfd;
5663                 int close_fd;
5664                 int closed;
5665
5666                 fd = redir->nfile.fd;
5667                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5668                         //bb_error_msg("doing %d > %d", fd, newfd);
5669                         newfd = redir->ndup.dupfd;
5670                         close_fd = -1;
5671                 } else {
5672                         newfd = openredirect(redir); /* always >= 0 */
5673                         if (fd == newfd) {
5674                                 /* open() gave us precisely the fd we wanted.
5675                                  * This means that this fd was not busy
5676                                  * (not opened to anywhere).
5677                                  * Remember to close it on restore:
5678                                  */
5679                                 add_squirrel_closed(sv, fd);
5680                                 continue;
5681                         }
5682                         close_fd = newfd;
5683                 }
5684
5685                 if (fd == newfd)
5686                         continue;
5687
5688                 /* if "N>FILE": move newfd to fd */
5689                 /* if "N>&M": dup newfd to fd */
5690                 /* if "N>&-": close fd (newfd is -1) */
5691
5692  IF_BASH_REDIR_OUTPUT(redirect_more:)
5693
5694                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5695                 if (newfd == -1) {
5696                         /* "N>&-" means "close me" */
5697                         if (!closed) {
5698                                 /* ^^^ optimization: saving may already
5699                                  * have closed it. If not... */
5700                                 close(fd);
5701                         }
5702                 } else {
5703                         /* if newfd is a script fd or saved fd, simulate EBADF */
5704                         if (internally_opened_fd(newfd, sv)) {
5705                                 errno = EBADF;
5706                                 ash_msg_and_raise_perror("%d", newfd);
5707                         }
5708                         dup2_or_raise(newfd, fd);
5709                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5710                                 close(close_fd);
5711 #if BASH_REDIR_OUTPUT
5712                         if (redir->nfile.type == NTO2 && fd == 1) {
5713                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5714                                 fd = 2;
5715                                 newfd = 1;
5716                                 close_fd = -1;
5717                                 goto redirect_more;
5718                         }
5719 #endif
5720                 }
5721         } while ((redir = redir->nfile.next) != NULL);
5722         INT_ON;
5723
5724 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5725 #define REDIR_SAVEFD2 0
5726         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5727         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5728         // not only for calls with flags containing REDIR_SAVEFD2.
5729         // We do this unconditionally (see save_fd_on_redirect()).
5730         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5731         //      preverrout_fd = copied_fd2;
5732 }
5733
5734 static int
5735 redirectsafe(union node *redir, int flags)
5736 {
5737         int err;
5738         volatile int saveint;
5739         struct jmploc *volatile savehandler = exception_handler;
5740         struct jmploc jmploc;
5741
5742         SAVE_INT(saveint);
5743         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5744         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5745         if (!err) {
5746                 exception_handler = &jmploc;
5747                 redirect(redir, flags);
5748         }
5749         exception_handler = savehandler;
5750         if (err && exception_type != EXERROR)
5751                 longjmp(exception_handler->loc, 1);
5752         RESTORE_INT(saveint);
5753         return err;
5754 }
5755
5756 static struct redirtab*
5757 pushredir(union node *redir)
5758 {
5759         struct redirtab *sv;
5760         int i;
5761
5762         if (!redir)
5763                 return redirlist;
5764
5765         i = 0;
5766         do {
5767                 i++;
5768 #if BASH_REDIR_OUTPUT
5769                 if (redir->nfile.type == NTO2)
5770                         i++;
5771 #endif
5772                 redir = redir->nfile.next;
5773         } while (redir);
5774
5775         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5776         sv->pair_count = i;
5777         while (--i >= 0)
5778                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5779         sv->next = redirlist;
5780         redirlist = sv;
5781         return sv->next;
5782 }
5783
5784 /*
5785  * Undo the effects of the last redirection.
5786  */
5787 static void
5788 popredir(int drop)
5789 {
5790         struct redirtab *rp;
5791         int i;
5792
5793         if (redirlist == NULL)
5794                 return;
5795         INT_OFF;
5796         rp = redirlist;
5797         for (i = 0; i < rp->pair_count; i++) {
5798                 int fd = rp->two_fd[i].orig_fd;
5799                 int copy = rp->two_fd[i].moved_to;
5800                 if (copy == CLOSED) {
5801                         if (!drop)
5802                                 close(fd);
5803                         continue;
5804                 }
5805                 if (copy != EMPTY) {
5806                         if (!drop) {
5807                                 /*close(fd);*/
5808                                 dup2_or_raise(copy, fd);
5809                         }
5810                         close(copy);
5811                 }
5812         }
5813         redirlist = rp->next;
5814         free(rp);
5815         INT_ON;
5816 }
5817
5818 static void
5819 unwindredir(struct redirtab *stop)
5820 {
5821         while (redirlist != stop)
5822                 popredir(/*drop:*/ 0);
5823 }
5824
5825
5826 /* ============ Routines to expand arguments to commands
5827  *
5828  * We have to deal with backquotes, shell variables, and file metacharacters.
5829  */
5830
5831 #if ENABLE_FEATURE_SH_MATH
5832 static arith_t
5833 ash_arith(const char *s)
5834 {
5835         arith_state_t math_state;
5836         arith_t result;
5837
5838         math_state.lookupvar = lookupvar;
5839         math_state.setvar    = setvar0;
5840         //math_state.endofname = endofname;
5841
5842         INT_OFF;
5843         result = arith(&math_state, s);
5844         if (math_state.errmsg)
5845                 ash_msg_and_raise_error(math_state.errmsg);
5846         INT_ON;
5847
5848         return result;
5849 }
5850 #endif
5851 #if BASH_SUBSTR
5852 # if ENABLE_FEATURE_SH_MATH
5853 static int substr_atoi(const char *s)
5854 {
5855         arith_t t = ash_arith(s);
5856         if (sizeof(t) > sizeof(int)) {
5857                 /* clamp very large or very large negative nums for ${v:N:M}:
5858                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5859                  */
5860                 if (t > INT_MAX)
5861                         t = INT_MAX;
5862                 if (t < INT_MIN)
5863                         t = INT_MIN;
5864         }
5865         return t;
5866 }
5867 # else
5868 #  define substr_atoi(s) number(s)
5869 # endif
5870 #endif
5871
5872 /*
5873  * expandarg flags
5874  */
5875 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5876 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5877 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5878 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5879 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5880  * POSIX says for this case:
5881  *  Pathname expansion shall not be performed on the word by a
5882  *  non-interactive shell; an interactive shell may perform it, but shall
5883  *  do so only when the expansion would result in one word.
5884  * Currently, our code complies to the above rule by never globbing
5885  * redirection filenames.
5886  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5887  * (this means that on a typical Linux distro, bash almost always
5888  * performs globbing, and thus diverges from what we do).
5889  */
5890 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5891 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5892 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5893 #define EXP_QUOTED      0x80    /* expand word in double quotes */
5894 /*
5895  * rmescape() flags
5896  */
5897 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5898 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5899 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5900 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5901
5902 /* Add CTLESC when necessary. */
5903 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5904 /* Do not skip NUL characters. */
5905 #define QUOTES_KEEPNUL EXP_TILDE
5906
5907 /*
5908  * Structure specifying which parts of the string should be searched
5909  * for IFS characters.
5910  */
5911 struct ifsregion {
5912         struct ifsregion *next; /* next region in list */
5913         int begoff;             /* offset of start of region */
5914         int endoff;             /* offset of end of region */
5915         int nulonly;            /* search for nul bytes only */
5916 };
5917
5918 struct arglist {
5919         struct strlist *list;
5920         struct strlist **lastp;
5921 };
5922
5923 /* output of current string */
5924 static char *expdest;
5925 /* list of back quote expressions */
5926 static struct nodelist *argbackq;
5927 /* first struct in list of ifs regions */
5928 static struct ifsregion ifsfirst;
5929 /* last struct in list */
5930 static struct ifsregion *ifslastp;
5931 /* holds expanded arg list */
5932 static struct arglist exparg;
5933
5934 /*
5935  * Our own itoa().
5936  * cvtnum() is used even if math support is off (to prepare $? values and such).
5937  */
5938 static int
5939 cvtnum(arith_t num)
5940 {
5941         int len;
5942
5943         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5944         len = sizeof(arith_t) * 3;
5945         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5946         if (sizeof(arith_t) < 4) len += 2;
5947
5948         expdest = makestrspace(len, expdest);
5949         len = fmtstr(expdest, len, ARITH_FMT, num);
5950         STADJUST(len, expdest);
5951         return len;
5952 }
5953
5954 /*
5955  * Break the argument string into pieces based upon IFS and add the
5956  * strings to the argument list.  The regions of the string to be
5957  * searched for IFS characters have been stored by recordregion.
5958  */
5959 static void
5960 ifsbreakup(char *string, struct arglist *arglist)
5961 {
5962         struct ifsregion *ifsp;
5963         struct strlist *sp;
5964         char *start;
5965         char *p;
5966         char *q;
5967         const char *ifs, *realifs;
5968         int ifsspc;
5969         int nulonly;
5970
5971         start = string;
5972         if (ifslastp != NULL) {
5973                 ifsspc = 0;
5974                 nulonly = 0;
5975                 realifs = ifsset() ? ifsval() : defifs;
5976                 ifsp = &ifsfirst;
5977                 do {
5978                         int afternul;
5979
5980                         p = string + ifsp->begoff;
5981                         afternul = nulonly;
5982                         nulonly = ifsp->nulonly;
5983                         ifs = nulonly ? nullstr : realifs;
5984                         ifsspc = 0;
5985                         while (p < string + ifsp->endoff) {
5986                                 q = p;
5987                                 if ((unsigned char)*p == CTLESC)
5988                                         p++;
5989                                 if (!strchr(ifs, *p)) {
5990                                         p++;
5991                                         continue;
5992                                 }
5993                                 if (!(afternul || nulonly))
5994                                         ifsspc = (strchr(defifs, *p) != NULL);
5995                                 /* Ignore IFS whitespace at start */
5996                                 if (q == start && ifsspc) {
5997                                         p++;
5998                                         start = p;
5999                                         continue;
6000                                 }
6001                                 *q = '\0';
6002                                 sp = stzalloc(sizeof(*sp));
6003                                 sp->text = start;
6004                                 *arglist->lastp = sp;
6005                                 arglist->lastp = &sp->next;
6006                                 p++;
6007                                 if (!nulonly) {
6008                                         for (;;) {
6009                                                 if (p >= string + ifsp->endoff) {
6010                                                         break;
6011                                                 }
6012                                                 q = p;
6013                                                 if ((unsigned char)*p == CTLESC)
6014                                                         p++;
6015                                                 if (strchr(ifs, *p) == NULL) {
6016                                                         p = q;
6017                                                         break;
6018                                                 }
6019                                                 if (strchr(defifs, *p) == NULL) {
6020                                                         if (ifsspc) {
6021                                                                 p++;
6022                                                                 ifsspc = 0;
6023                                                         } else {
6024                                                                 p = q;
6025                                                                 break;
6026                                                         }
6027                                                 } else
6028                                                         p++;
6029                                         }
6030                                 }
6031                                 start = p;
6032                         } /* while */
6033                         ifsp = ifsp->next;
6034                 } while (ifsp != NULL);
6035                 if (nulonly)
6036                         goto add;
6037         }
6038
6039         if (!*start)
6040                 return;
6041
6042  add:
6043         sp = stzalloc(sizeof(*sp));
6044         sp->text = start;
6045         *arglist->lastp = sp;
6046         arglist->lastp = &sp->next;
6047 }
6048
6049 static void
6050 ifsfree(void)
6051 {
6052         struct ifsregion *p = ifsfirst.next;
6053
6054         if (!p)
6055                 goto out;
6056
6057         INT_OFF;
6058         do {
6059                 struct ifsregion *ifsp;
6060                 ifsp = p->next;
6061                 free(p);
6062                 p = ifsp;
6063         } while (p);
6064         ifsfirst.next = NULL;
6065         INT_ON;
6066  out:
6067         ifslastp = NULL;
6068 }
6069
6070 static size_t
6071 esclen(const char *start, const char *p)
6072 {
6073         size_t esc = 0;
6074
6075         while (p > start && (unsigned char)*--p == CTLESC) {
6076                 esc++;
6077         }
6078         return esc;
6079 }
6080
6081 /*
6082  * Remove any CTLESC characters from a string.
6083  */
6084 #if !BASH_PATTERN_SUBST
6085 #define rmescapes(str, flag, slash_position) \
6086         rmescapes(str, flag)
6087 #endif
6088 static char *
6089 rmescapes(char *str, int flag, int *slash_position)
6090 {
6091         static const char qchars[] ALIGN1 = {
6092                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6093
6094         char *p, *q, *r;
6095         unsigned protect_against_glob;
6096         unsigned globbing;
6097
6098         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6099         if (!p)
6100                 return str;
6101
6102         q = p;
6103         r = str;
6104         if (flag & RMESCAPE_ALLOC) {
6105                 size_t len = p - str;
6106                 size_t fulllen = len + strlen(p) + 1;
6107
6108                 if (flag & RMESCAPE_GROW) {
6109                         int strloc = str - (char *)stackblock();
6110                         r = makestrspace(fulllen, expdest);
6111                         /* p and str may be invalidated by makestrspace */
6112                         str = (char *)stackblock() + strloc;
6113                         p = str + len;
6114                 } else if (flag & RMESCAPE_HEAP) {
6115                         r = ckmalloc(fulllen);
6116                 } else {
6117                         r = stalloc(fulllen);
6118                 }
6119                 q = r;
6120                 if (len > 0) {
6121                         q = (char *)mempcpy(q, str, len);
6122                 }
6123         }
6124
6125         globbing = flag & RMESCAPE_GLOB;
6126         protect_against_glob = globbing;
6127         while (*p) {
6128                 if ((unsigned char)*p == CTLQUOTEMARK) {
6129 // Note: protect_against_glob only affect whether
6130 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6131                         p++;
6132                         protect_against_glob = globbing;
6133                         continue;
6134                 }
6135                 if (*p == '\\') {
6136                         /* naked back slash */
6137                         protect_against_glob = 0;
6138                         goto copy;
6139                 }
6140                 if ((unsigned char)*p == CTLESC) {
6141                         p++;
6142 #if DEBUG
6143                         if (*p == '\0')
6144                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6145 #endif
6146                         if (protect_against_glob) {
6147                                 /*
6148                                  * We used to trust glob() and fnmatch() to eat
6149                                  * superfluous escapes (\z where z has no
6150                                  * special meaning anyway). But this causes
6151                                  * bugs such as string of one greek letter rho
6152                                  * (unicode-encoded as two bytes "cf,81")
6153                                  * getting encoded as "cf,CTLESC,81"
6154                                  * and here, converted to "cf,\,81" -
6155                                  * which does not go well with some flavors
6156                                  * of fnmatch() in unicode locales
6157                                  * (for example, glibc <= 2.22).
6158                                  *
6159                                  * Lets add "\" only on the chars which need it.
6160                                  * Testcases for less obvious chars are shown.
6161                                  */
6162                                 if (*p == '*'
6163                                  || *p == '?'
6164                                  || *p == '['
6165                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6166                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6167                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6168                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6169                                 /* Some libc support [^negate], that's why "^" also needs love */
6170                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6171                                 ) {
6172                                         *q++ = '\\';
6173                                 }
6174                         }
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                         /* "$@" syntax adherence hack */
6657                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6658                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6659                                 goto start;
6660                         }
6661                         inquotes ^= EXP_QUOTED;
6662  addquote:
6663                         if (flags & QUOTES_ESC) {
6664                                 p--;
6665                                 length++;
6666                                 startloc++;
6667                         }
6668                         break;
6669                 case CTLESC:
6670                         startloc++;
6671                         length++;
6672                         goto addquote;
6673                 case CTLVAR:
6674                         TRACE(("argstr: evalvar('%s')\n", p));
6675                         p = evalvar(p, flags | inquotes);
6676                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6677                         goto start;
6678                 case CTLBACKQ:
6679                         expbackq(argbackq->n, flags | inquotes);
6680                         argbackq = argbackq->next;
6681                         goto start;
6682 #if ENABLE_FEATURE_SH_MATH
6683                 case CTLENDARI:
6684                         p--;
6685                         expari(flags | inquotes);
6686                         goto start;
6687 #endif
6688                 }
6689         }
6690  breakloop: ;
6691 }
6692
6693 static char *
6694 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6695                 char *pattern, int quotes, int zero)
6696 {
6697         char *loc, *loc2;
6698         char c;
6699
6700         loc = startp;
6701         loc2 = rmesc;
6702         do {
6703                 int match;
6704                 const char *s = loc2;
6705
6706                 c = *loc2;
6707                 if (zero) {
6708                         *loc2 = '\0';
6709                         s = rmesc;
6710                 }
6711                 match = pmatch(pattern, s);
6712
6713                 *loc2 = c;
6714                 if (match)
6715                         return loc;
6716                 if (quotes && (unsigned char)*loc == CTLESC)
6717                         loc++;
6718                 loc++;
6719                 loc2++;
6720         } while (c);
6721         return NULL;
6722 }
6723
6724 static char *
6725 scanright(char *startp, char *rmesc, char *rmescend,
6726                 char *pattern, int quotes, int match_at_start)
6727 {
6728 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6729         int try2optimize = match_at_start;
6730 #endif
6731         int esc = 0;
6732         char *loc;
6733         char *loc2;
6734
6735         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6736          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6737          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6738          * Logic:
6739          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6740          * and on each iteration they go back two/one char until they reach the beginning.
6741          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6742          */
6743         /* TODO: document in what other circumstances we are called. */
6744
6745         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6746                 int match;
6747                 char c = *loc2;
6748                 const char *s = loc2;
6749                 if (match_at_start) {
6750                         *loc2 = '\0';
6751                         s = rmesc;
6752                 }
6753                 match = pmatch(pattern, s);
6754                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6755                 *loc2 = c;
6756                 if (match)
6757                         return loc;
6758 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6759                 if (try2optimize) {
6760                         /* Maybe we can optimize this:
6761                          * if pattern ends with unescaped *, we can avoid checking
6762                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6763                          * it won't match truncated "raw_value_of_" strings too.
6764                          */
6765                         unsigned plen = strlen(pattern);
6766                         /* Does it end with "*"? */
6767                         if (plen != 0 && pattern[--plen] == '*') {
6768                                 /* "xxxx*" is not escaped */
6769                                 /* "xxx\*" is escaped */
6770                                 /* "xx\\*" is not escaped */
6771                                 /* "x\\\*" is escaped */
6772                                 int slashes = 0;
6773                                 while (plen != 0 && pattern[--plen] == '\\')
6774                                         slashes++;
6775                                 if (!(slashes & 1))
6776                                         break; /* ends with unescaped "*" */
6777                         }
6778                         try2optimize = 0;
6779                 }
6780 #endif
6781                 loc--;
6782                 if (quotes) {
6783                         if (--esc < 0) {
6784                                 esc = esclen(startp, loc);
6785                         }
6786                         if (esc % 2) {
6787                                 esc--;
6788                                 loc--;
6789                         }
6790                 }
6791         }
6792         return NULL;
6793 }
6794
6795 static void varunset(const char *, const char *, const char *, int) NORETURN;
6796 static void
6797 varunset(const char *end, const char *var, const char *umsg, int varflags)
6798 {
6799         const char *msg;
6800         const char *tail;
6801
6802         tail = nullstr;
6803         msg = "parameter not set";
6804         if (umsg) {
6805                 if ((unsigned char)*end == CTLENDVAR) {
6806                         if (varflags & VSNUL)
6807                                 tail = " or null";
6808                 } else {
6809                         msg = umsg;
6810                 }
6811         }
6812         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6813 }
6814
6815 static const char *
6816 subevalvar(char *p, char *varname, int strloc, int subtype,
6817                 int startloc, int varflags, int flag)
6818 {
6819         struct nodelist *saveargbackq = argbackq;
6820         int quotes = flag & QUOTES_ESC;
6821         char *startp;
6822         char *loc;
6823         char *rmesc, *rmescend;
6824         char *str;
6825         int amount, resetloc;
6826         int argstr_flags;
6827         IF_BASH_PATTERN_SUBST(int workloc;)
6828         IF_BASH_PATTERN_SUBST(int slash_pos;)
6829         IF_BASH_PATTERN_SUBST(char *repl;)
6830         int zero;
6831         char *(*scan)(char*, char*, char*, char*, int, int);
6832
6833         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6834         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6835
6836 #if BASH_PATTERN_SUBST
6837         /* For "${v/pattern/repl}", we must find the delimiter _before_
6838          * argstr() call expands possible variable references in pattern:
6839          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6840          */
6841         repl = NULL;
6842         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6843                 /* Find '/' and replace with NUL */
6844                 repl = p;
6845                 for (;;) {
6846                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6847                         if (*repl == '\0') {
6848                                 repl = NULL;
6849                                 break;
6850                         }
6851                         if (*repl == '/') {
6852                                 *repl = '\0';
6853                                 break;
6854                         }
6855                         if ((unsigned char)*repl == CTLESC && repl[1])
6856                                 repl++;
6857                         repl++;
6858                 }
6859         }
6860 #endif
6861         argstr_flags = EXP_TILDE;
6862         if (subtype != VSASSIGN
6863          && subtype != VSQUESTION
6864 #if BASH_SUBSTR
6865          && subtype != VSSUBSTR
6866 #endif
6867         ) {
6868                 /* EXP_CASE keeps CTLESC's */
6869                 argstr_flags = EXP_TILDE | EXP_CASE;
6870         }
6871         argstr(p, argstr_flags);
6872         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6873 #if BASH_PATTERN_SUBST
6874         slash_pos = -1;
6875         if (repl) {
6876                 slash_pos = expdest - ((char *)stackblock() + strloc);
6877                 STPUTC('/', expdest);
6878                 //bb_error_msg("repl+1:'%s'", repl + 1);
6879                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6880                 *repl = '/';
6881         }
6882 #endif
6883         STPUTC('\0', expdest);
6884         argbackq = saveargbackq;
6885         startp = (char *)stackblock() + startloc;
6886         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6887
6888         switch (subtype) {
6889         case VSASSIGN:
6890                 setvar0(varname, startp);
6891                 amount = startp - expdest;
6892                 STADJUST(amount, expdest);
6893                 return startp;
6894
6895         case VSQUESTION:
6896                 varunset(p, varname, startp, varflags);
6897                 /* NOTREACHED */
6898
6899 #if BASH_SUBSTR
6900         case VSSUBSTR: {
6901                 int pos, len, orig_len;
6902                 char *colon;
6903
6904                 loc = str = stackblock() + strloc;
6905
6906                 /* Read POS in ${var:POS:LEN} */
6907                 colon = strchr(loc, ':');
6908                 if (colon) *colon = '\0';
6909                 pos = substr_atoi(loc);
6910                 if (colon) *colon = ':';
6911
6912                 /* Read LEN in ${var:POS:LEN} */
6913                 len = str - startp - 1;
6914                 /* *loc != '\0', guaranteed by parser */
6915                 if (quotes) {
6916                         char *ptr;
6917                         /* Adjust the length by the number of escapes */
6918                         for (ptr = startp; ptr < (str - 1); ptr++) {
6919                                 if ((unsigned char)*ptr == CTLESC) {
6920                                         len--;
6921                                         ptr++;
6922                                 }
6923                         }
6924                 }
6925                 orig_len = len;
6926                 if (*loc++ == ':') {
6927                         /* ${var::LEN} */
6928                         len = substr_atoi(loc);
6929                 } else {
6930                         /* Skip POS in ${var:POS:LEN} */
6931                         len = orig_len;
6932                         while (*loc && *loc != ':')
6933                                 loc++;
6934                         if (*loc++ == ':')
6935                                 len = substr_atoi(loc);
6936                 }
6937                 if (pos < 0) {
6938                         /* ${VAR:$((-n)):l} starts n chars from the end */
6939                         pos = orig_len + pos;
6940                 }
6941                 if ((unsigned)pos >= orig_len) {
6942                         /* apart from obvious ${VAR:999999:l},
6943                          * covers ${VAR:$((-9999999)):l} - result is ""
6944                          * (bash compat)
6945                          */
6946                         pos = 0;
6947                         len = 0;
6948                 }
6949                 if (len < 0) {
6950                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6951                         len = (orig_len - pos) + len;
6952                 }
6953                 if ((unsigned)len > (orig_len - pos))
6954                         len = orig_len - pos;
6955
6956                 for (str = startp; pos; str++, pos--) {
6957                         if (quotes && (unsigned char)*str == CTLESC)
6958                                 str++;
6959                 }
6960                 for (loc = startp; len; len--) {
6961                         if (quotes && (unsigned char)*str == CTLESC)
6962                                 *loc++ = *str++;
6963                         *loc++ = *str++;
6964                 }
6965                 *loc = '\0';
6966                 amount = loc - expdest;
6967                 STADJUST(amount, expdest);
6968                 return loc;
6969         }
6970 #endif /* BASH_SUBSTR */
6971         }
6972
6973         resetloc = expdest - (char *)stackblock();
6974
6975 #if BASH_PATTERN_SUBST
6976         repl = NULL;
6977
6978         /* We'll comeback here if we grow the stack while handling
6979          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6980          * stack will need rebasing, and we'll need to remove our work
6981          * areas each time
6982          */
6983  restart:
6984 #endif
6985
6986         amount = expdest - ((char *)stackblock() + resetloc);
6987         STADJUST(-amount, expdest);
6988         startp = (char *)stackblock() + startloc;
6989
6990         rmesc = startp;
6991         rmescend = (char *)stackblock() + strloc;
6992         //bb_error_msg("str7:'%s'", rmescend);
6993         if (quotes) {
6994 //TODO: how to handle slash_pos here if string changes (shortens?)
6995                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6996                 if (rmesc != startp) {
6997                         rmescend = expdest;
6998                         startp = (char *)stackblock() + startloc;
6999                 }
7000         }
7001         rmescend--;
7002         str = (char *)stackblock() + strloc;
7003         /*
7004          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7005          * The result is a_\_z_c (not a\_\_z_c)!
7006          *
7007          * The search pattern and replace string treat backslashes differently!
7008          * "&slash_pos" causes rmescapes() to work differently on the pattern
7009          * and string.  It's only used on the first call.
7010          */
7011         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7012         rmescapes(str, RMESCAPE_GLOB,
7013                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7014         );
7015
7016 #if BASH_PATTERN_SUBST
7017         workloc = expdest - (char *)stackblock();
7018         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7019                 int len;
7020                 char *idx, *end;
7021
7022                 if (!repl) {
7023                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7024                         repl = nullstr;
7025                         if (slash_pos >= 0) {
7026                                 repl = str + slash_pos;
7027                                 *repl++ = '\0';
7028                         }
7029                 }
7030                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7031
7032                 /* If there's no pattern to match, return the expansion unmolested */
7033                 if (str[0] == '\0')
7034                         return NULL;
7035
7036                 len = 0;
7037                 idx = startp;
7038                 end = str - 1;
7039                 while (idx < end) {
7040  try_to_match:
7041                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7042                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7043                         if (!loc) {
7044                                 /* No match, advance */
7045                                 char *restart_detect = stackblock();
7046  skip_matching:
7047                                 STPUTC(*idx, expdest);
7048                                 if (quotes && (unsigned char)*idx == CTLESC) {
7049                                         idx++;
7050                                         len++;
7051                                         STPUTC(*idx, expdest);
7052                                 }
7053                                 if (stackblock() != restart_detect)
7054                                         goto restart;
7055                                 idx++;
7056                                 len++;
7057                                 rmesc++;
7058                                 /* continue; - prone to quadratic behavior, smarter code: */
7059                                 if (idx >= end)
7060                                         break;
7061                                 if (str[0] == '*') {
7062                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7063                                          * it would never match "ong_string" etc, no point in trying.
7064                                          */
7065                                         goto skip_matching;
7066                                 }
7067                                 goto try_to_match;
7068                         }
7069
7070                         if (subtype == VSREPLACEALL) {
7071                                 while (idx < loc) {
7072                                         if (quotes && (unsigned char)*idx == CTLESC)
7073                                                 idx++;
7074                                         idx++;
7075                                         rmesc++;
7076                                 }
7077                         } else {
7078                                 idx = loc;
7079                         }
7080
7081                         //bb_error_msg("repl:'%s'", repl);
7082                         for (loc = (char*)repl; *loc; loc++) {
7083                                 char *restart_detect = stackblock();
7084                                 if (quotes && *loc == '\\') {
7085                                         STPUTC(CTLESC, expdest);
7086                                         len++;
7087                                 }
7088                                 STPUTC(*loc, expdest);
7089                                 if (stackblock() != restart_detect)
7090                                         goto restart;
7091                                 len++;
7092                         }
7093
7094                         if (subtype == VSREPLACE) {
7095                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7096                                 while (*idx) {
7097                                         char *restart_detect = stackblock();
7098                                         STPUTC(*idx, expdest);
7099                                         if (stackblock() != restart_detect)
7100                                                 goto restart;
7101                                         len++;
7102                                         idx++;
7103                                 }
7104                                 break;
7105                         }
7106                 }
7107
7108                 /* We've put the replaced text into a buffer at workloc, now
7109                  * move it to the right place and adjust the stack.
7110                  */
7111                 STPUTC('\0', expdest);
7112                 startp = (char *)stackblock() + startloc;
7113                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7114                 //bb_error_msg("startp:'%s'", startp);
7115                 amount = expdest - (startp + len);
7116                 STADJUST(-amount, expdest);
7117                 return startp;
7118         }
7119 #endif /* BASH_PATTERN_SUBST */
7120
7121         subtype -= VSTRIMRIGHT;
7122 #if DEBUG
7123         if (subtype < 0 || subtype > 7)
7124                 abort();
7125 #endif
7126         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7127         zero = subtype >> 1;
7128         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7129         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7130
7131         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7132         if (loc) {
7133                 if (zero) {
7134                         memmove(startp, loc, str - loc);
7135                         loc = startp + (str - loc) - 1;
7136                 }
7137                 *loc = '\0';
7138                 amount = loc - expdest;
7139                 STADJUST(amount, expdest);
7140         }
7141         return loc;
7142 }
7143
7144 /*
7145  * Add the value of a specialized variable to the stack string.
7146  * name parameter (examples):
7147  * ash -c 'echo $1'      name:'1='
7148  * ash -c 'echo $qwe'    name:'qwe='
7149  * ash -c 'echo $$'      name:'$='
7150  * ash -c 'echo ${$}'    name:'$='
7151  * ash -c 'echo ${$##q}' name:'$=q'
7152  * ash -c 'echo ${#$}'   name:'$='
7153  * note: examples with bad shell syntax:
7154  * ash -c 'echo ${#$1}'  name:'$=1'
7155  * ash -c 'echo ${#1#}'  name:'1=#'
7156  */
7157 static NOINLINE ssize_t
7158 varvalue(char *name, int varflags, int flags, int *quotedp)
7159 {
7160         const char *p;
7161         int num;
7162         int i;
7163         ssize_t len = 0;
7164         int sep;
7165         int quoted = *quotedp;
7166         int subtype = varflags & VSTYPE;
7167         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7168         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7169         int syntax;
7170
7171         sep = (flags & EXP_FULL) << CHAR_BIT;
7172         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7173
7174         switch (*name) {
7175         case '$':
7176                 num = rootpid;
7177                 goto numvar;
7178         case '?':
7179                 num = exitstatus;
7180                 goto numvar;
7181         case '#':
7182                 num = shellparam.nparam;
7183                 goto numvar;
7184         case '!':
7185                 num = backgndpid;
7186                 if (num == 0)
7187                         return -1;
7188  numvar:
7189                 len = cvtnum(num);
7190                 goto check_1char_name;
7191         case '-':
7192                 expdest = makestrspace(NOPTS, expdest);
7193                 for (i = NOPTS - 1; i >= 0; i--) {
7194                         if (optlist[i] && optletters(i)) {
7195                                 USTPUTC(optletters(i), expdest);
7196                                 len++;
7197                         }
7198                 }
7199  check_1char_name:
7200 #if 0
7201                 /* handles cases similar to ${#$1} */
7202                 if (name[2] != '\0')
7203                         raise_error_syntax("bad substitution");
7204 #endif
7205                 break;
7206         case '@':
7207                 if (quoted && sep)
7208                         goto param;
7209                 /* fall through */
7210         case '*': {
7211                 char **ap;
7212                 char sepc;
7213
7214                 if (quoted)
7215                         sep = 0;
7216                 sep |= ifsset() ? ifsval()[0] : ' ';
7217  param:
7218                 sepc = sep;
7219                 *quotedp = !sepc;
7220                 ap = shellparam.p;
7221                 if (!ap)
7222                         return -1;
7223                 while ((p = *ap++) != NULL) {
7224                         len += strtodest(p, syntax, quotes);
7225
7226                         if (*ap && sep) {
7227                                 len++;
7228                                 memtodest(&sepc, 1, syntax, quotes);
7229                         }
7230                 }
7231                 break;
7232         } /* case '*' */
7233         case '0':
7234         case '1':
7235         case '2':
7236         case '3':
7237         case '4':
7238         case '5':
7239         case '6':
7240         case '7':
7241         case '8':
7242         case '9':
7243                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7244                 if (num < 0 || num > shellparam.nparam)
7245                         return -1;
7246                 p = num ? shellparam.p[num - 1] : arg0;
7247                 goto value;
7248         default:
7249                 /* NB: name has form "VAR=..." */
7250                 p = lookupvar(name);
7251  value:
7252                 if (!p)
7253                         return -1;
7254
7255                 len = strtodest(p, syntax, quotes);
7256 #if ENABLE_UNICODE_SUPPORT
7257                 if (subtype == VSLENGTH && len > 0) {
7258                         reinit_unicode_for_ash();
7259                         if (unicode_status == UNICODE_ON) {
7260                                 STADJUST(-len, expdest);
7261                                 discard = 0;
7262                                 len = unicode_strlen(p);
7263                         }
7264                 }
7265 #endif
7266                 break;
7267         }
7268
7269         if (discard)
7270                 STADJUST(-len, expdest);
7271         return len;
7272 }
7273
7274 /*
7275  * Expand a variable, and return a pointer to the next character in the
7276  * input string.
7277  */
7278 static char *
7279 evalvar(char *p, int flag)
7280 {
7281         char varflags;
7282         char subtype;
7283         int quoted;
7284         char easy;
7285         char *var;
7286         int patloc;
7287         int startloc;
7288         ssize_t varlen;
7289
7290         varflags = (unsigned char) *p++;
7291         subtype = varflags & VSTYPE;
7292
7293         if (!subtype)
7294                 raise_error_syntax("bad substitution");
7295
7296         quoted = flag & EXP_QUOTED;
7297         var = p;
7298         easy = (!quoted || (*var == '@' && shellparam.nparam));
7299         startloc = expdest - (char *)stackblock();
7300         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7301
7302  again:
7303         varlen = varvalue(var, varflags, flag, &quoted);
7304         if (varflags & VSNUL)
7305                 varlen--;
7306
7307         if (subtype == VSPLUS) {
7308                 varlen = -1 - varlen;
7309                 goto vsplus;
7310         }
7311
7312         if (subtype == VSMINUS) {
7313  vsplus:
7314                 if (varlen < 0) {
7315                         argstr(
7316                                 p,
7317                                 flag | EXP_TILDE | EXP_WORD
7318                         );
7319                         goto end;
7320                 }
7321                 goto record;
7322         }
7323
7324         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7325                 if (varlen >= 0)
7326                         goto record;
7327
7328                 subevalvar(p, var, 0, subtype, startloc, varflags,
7329                            flag & ~QUOTES_ESC);
7330                 varflags &= ~VSNUL;
7331                 /*
7332                  * Remove any recorded regions beyond
7333                  * start of variable
7334                  */
7335                 removerecordregions(startloc);
7336                 goto again;
7337         }
7338
7339         if (varlen < 0 && uflag)
7340                 varunset(p, var, 0, 0);
7341
7342         if (subtype == VSLENGTH) {
7343                 cvtnum(varlen > 0 ? varlen : 0);
7344                 goto record;
7345         }
7346
7347         if (subtype == VSNORMAL) {
7348  record:
7349                 if (!easy)
7350                         goto end;
7351                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7352                 goto end;
7353         }
7354
7355 #if DEBUG
7356         switch (subtype) {
7357         case VSTRIMLEFT:
7358         case VSTRIMLEFTMAX:
7359         case VSTRIMRIGHT:
7360         case VSTRIMRIGHTMAX:
7361 #if BASH_SUBSTR
7362         case VSSUBSTR:
7363 #endif
7364 #if BASH_PATTERN_SUBST
7365         case VSREPLACE:
7366         case VSREPLACEALL:
7367 #endif
7368                 break;
7369         default:
7370                 abort();
7371         }
7372 #endif
7373
7374         if (varlen >= 0) {
7375                 /*
7376                  * Terminate the string and start recording the pattern
7377                  * right after it
7378                  */
7379                 STPUTC('\0', expdest);
7380                 patloc = expdest - (char *)stackblock();
7381                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7382                                 startloc, varflags, flag)) {
7383                         int amount = expdest - (
7384                                 (char *)stackblock() + patloc - 1
7385                         );
7386                         STADJUST(-amount, expdest);
7387                 }
7388                 /* Remove any recorded regions beyond start of variable */
7389                 removerecordregions(startloc);
7390                 goto record;
7391         }
7392
7393  end:
7394         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7395                 int nesting = 1;
7396                 for (;;) {
7397                         unsigned char c = *p++;
7398                         if (c == CTLESC)
7399                                 p++;
7400                         else if (c == CTLBACKQ) {
7401                                 if (varlen >= 0)
7402                                         argbackq = argbackq->next;
7403                         } else if (c == CTLVAR) {
7404                                 if ((*p++ & VSTYPE) != VSNORMAL)
7405                                         nesting++;
7406                         } else if (c == CTLENDVAR) {
7407                                 if (--nesting == 0)
7408                                         break;
7409                         }
7410                 }
7411         }
7412         return p;
7413 }
7414
7415 /*
7416  * Add a file name to the list.
7417  */
7418 static void
7419 addfname(const char *name)
7420 {
7421         struct strlist *sp;
7422
7423         sp = stzalloc(sizeof(*sp));
7424         sp->text = sstrdup(name);
7425         *exparg.lastp = sp;
7426         exparg.lastp = &sp->next;
7427 }
7428
7429 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7430 static int
7431 hasmeta(const char *p)
7432 {
7433         static const char chars[] ALIGN1 = {
7434                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7435         };
7436
7437         for (;;) {
7438                 p = strpbrk(p, chars);
7439                 if (!p)
7440                         break;
7441                 switch ((unsigned char)*p) {
7442                 case CTLQUOTEMARK:
7443                         for (;;) {
7444                                 p++;
7445                                 if ((unsigned char)*p == CTLQUOTEMARK)
7446                                         break;
7447                                 if ((unsigned char)*p == CTLESC)
7448                                         p++;
7449                                 if (*p == '\0') /* huh? */
7450                                         return 0;
7451                         }
7452                         break;
7453                 case '\\':
7454                 case CTLESC:
7455                         p++;
7456                         if (*p == '\0')
7457                                 return 0;
7458                         break;
7459                 case '[':
7460                         if (!strchr(p + 1, ']')) {
7461                                 /* It's not a properly closed [] pattern,
7462                                  * but other metas may follow. Continue checking.
7463                                  * my[file* _is_ globbed by bash
7464                                  * and matches filenames like "my[file1".
7465                                  */
7466                                 break;
7467                         }
7468                         /* fallthrough */
7469                 default:
7470                 /* case '*': */
7471                 /* case '?': */
7472                         return 1;
7473                 }
7474                 p++;
7475         }
7476
7477         return 0;
7478 }
7479
7480 /* If we want to use glob() from libc... */
7481 #if !ENABLE_ASH_INTERNAL_GLOB
7482
7483 /* Add the result of glob() to the list */
7484 static void
7485 addglob(const glob_t *pglob)
7486 {
7487         char **p = pglob->gl_pathv;
7488
7489         do {
7490                 addfname(*p);
7491         } while (*++p);
7492 }
7493 static void
7494 expandmeta(struct strlist *str /*, int flag*/)
7495 {
7496         /* TODO - EXP_REDIR */
7497
7498         while (str) {
7499                 char *p;
7500                 glob_t pglob;
7501                 int i;
7502
7503                 if (fflag)
7504                         goto nometa;
7505
7506                 if (!hasmeta(str->text))
7507                         goto nometa;
7508
7509                 INT_OFF;
7510                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7511 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7512 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7513 //
7514 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7515 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7516 // Which means you need to unescape the string, right? Not so fast:
7517 // if there _is_ a file named "file\?" (with backslash), it is returned
7518 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7519 // You DON'T KNOW by looking at the result whether you need to unescape it.
7520 //
7521 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7522 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7523 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7524 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7525 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7526 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7527                 i = glob(p, 0, NULL, &pglob);
7528                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7529                 if (p != str->text)
7530                         free(p);
7531                 switch (i) {
7532                 case 0:
7533 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7534                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7535                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7536                                 goto nometa2;
7537 #endif
7538                         addglob(&pglob);
7539                         globfree(&pglob);
7540                         INT_ON;
7541                         break;
7542                 case GLOB_NOMATCH:
7543  //nometa2:
7544                         globfree(&pglob);
7545                         INT_ON;
7546  nometa:
7547                         *exparg.lastp = str;
7548                         rmescapes(str->text, 0, NULL);
7549                         exparg.lastp = &str->next;
7550                         break;
7551                 default:        /* GLOB_NOSPACE */
7552                         globfree(&pglob);
7553                         INT_ON;
7554                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7555                 }
7556                 str = str->next;
7557         }
7558 }
7559
7560 #else
7561 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7562
7563 /*
7564  * Do metacharacter (i.e. *, ?, [...]) expansion.
7565  */
7566 static void
7567 expmeta(char *expdir, char *enddir, char *name)
7568 {
7569         char *p;
7570         const char *cp;
7571         char *start;
7572         char *endname;
7573         int metaflag;
7574         struct stat statb;
7575         DIR *dirp;
7576         struct dirent *dp;
7577         int atend;
7578         int matchdot;
7579         int esc;
7580
7581         metaflag = 0;
7582         start = name;
7583         for (p = name; esc = 0, *p; p += esc + 1) {
7584                 if (*p == '*' || *p == '?')
7585                         metaflag = 1;
7586                 else if (*p == '[') {
7587                         char *q = p + 1;
7588                         if (*q == '!')
7589                                 q++;
7590                         for (;;) {
7591                                 if (*q == '\\')
7592                                         q++;
7593                                 if (*q == '/' || *q == '\0')
7594                                         break;
7595                                 if (*++q == ']') {
7596                                         metaflag = 1;
7597                                         break;
7598                                 }
7599                         }
7600                 } else {
7601                         if (*p == '\\')
7602                                 esc++;
7603                         if (p[esc] == '/') {
7604                                 if (metaflag)
7605                                         break;
7606                                 start = p + esc + 1;
7607                         }
7608                 }
7609         }
7610         if (metaflag == 0) {    /* we've reached the end of the file name */
7611                 if (enddir != expdir)
7612                         metaflag++;
7613                 p = name;
7614                 do {
7615                         if (*p == '\\')
7616                                 p++;
7617                         *enddir++ = *p;
7618                 } while (*p++);
7619                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7620                         addfname(expdir);
7621                 return;
7622         }
7623         endname = p;
7624         if (name < start) {
7625                 p = name;
7626                 do {
7627                         if (*p == '\\')
7628                                 p++;
7629                         *enddir++ = *p++;
7630                 } while (p < start);
7631         }
7632         if (enddir == expdir) {
7633                 cp = ".";
7634         } else if (enddir == expdir + 1 && *expdir == '/') {
7635                 cp = "/";
7636         } else {
7637                 cp = expdir;
7638                 enddir[-1] = '\0';
7639         }
7640         dirp = opendir(cp);
7641         if (dirp == NULL)
7642                 return;
7643         if (enddir != expdir)
7644                 enddir[-1] = '/';
7645         if (*endname == 0) {
7646                 atend = 1;
7647         } else {
7648                 atend = 0;
7649                 *endname = '\0';
7650                 endname += esc + 1;
7651         }
7652         matchdot = 0;
7653         p = start;
7654         if (*p == '\\')
7655                 p++;
7656         if (*p == '.')
7657                 matchdot++;
7658         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7659                 if (dp->d_name[0] == '.' && !matchdot)
7660                         continue;
7661                 if (pmatch(start, dp->d_name)) {
7662                         if (atend) {
7663                                 strcpy(enddir, dp->d_name);
7664                                 addfname(expdir);
7665                         } else {
7666                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7667                                         continue;
7668                                 p[-1] = '/';
7669                                 expmeta(expdir, p, endname);
7670                         }
7671                 }
7672         }
7673         closedir(dirp);
7674         if (!atend)
7675                 endname[-esc - 1] = esc ? '\\' : '/';
7676 }
7677
7678 static struct strlist *
7679 msort(struct strlist *list, int len)
7680 {
7681         struct strlist *p, *q = NULL;
7682         struct strlist **lpp;
7683         int half;
7684         int n;
7685
7686         if (len <= 1)
7687                 return list;
7688         half = len >> 1;
7689         p = list;
7690         for (n = half; --n >= 0;) {
7691                 q = p;
7692                 p = p->next;
7693         }
7694         q->next = NULL;                 /* terminate first half of list */
7695         q = msort(list, half);          /* sort first half of list */
7696         p = msort(p, len - half);               /* sort second half */
7697         lpp = &list;
7698         for (;;) {
7699 #if ENABLE_LOCALE_SUPPORT
7700                 if (strcoll(p->text, q->text) < 0)
7701 #else
7702                 if (strcmp(p->text, q->text) < 0)
7703 #endif
7704                                                 {
7705                         *lpp = p;
7706                         lpp = &p->next;
7707                         p = *lpp;
7708                         if (p == NULL) {
7709                                 *lpp = q;
7710                                 break;
7711                         }
7712                 } else {
7713                         *lpp = q;
7714                         lpp = &q->next;
7715                         q = *lpp;
7716                         if (q == NULL) {
7717                                 *lpp = p;
7718                                 break;
7719                         }
7720                 }
7721         }
7722         return list;
7723 }
7724
7725 /*
7726  * Sort the results of file name expansion.  It calculates the number of
7727  * strings to sort and then calls msort (short for merge sort) to do the
7728  * work.
7729  */
7730 static struct strlist *
7731 expsort(struct strlist *str)
7732 {
7733         int len;
7734         struct strlist *sp;
7735
7736         len = 0;
7737         for (sp = str; sp; sp = sp->next)
7738                 len++;
7739         return msort(str, len);
7740 }
7741
7742 static void
7743 expandmeta(struct strlist *str /*, int flag*/)
7744 {
7745         /* TODO - EXP_REDIR */
7746
7747         while (str) {
7748                 char *expdir;
7749                 struct strlist **savelastp;
7750                 struct strlist *sp;
7751                 char *p;
7752
7753                 if (fflag)
7754                         goto nometa;
7755                 if (!hasmeta(str->text))
7756                         goto nometa;
7757                 savelastp = exparg.lastp;
7758
7759                 INT_OFF;
7760                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7761                 {
7762                         int i = strlen(str->text);
7763 //BUGGY estimation of how long expanded name can be
7764                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7765                 }
7766                 expmeta(expdir, expdir, p);
7767                 free(expdir);
7768                 if (p != str->text)
7769                         free(p);
7770                 INT_ON;
7771                 if (exparg.lastp == savelastp) {
7772                         /*
7773                          * no matches
7774                          */
7775  nometa:
7776                         *exparg.lastp = str;
7777                         rmescapes(str->text, 0, NULL);
7778                         exparg.lastp = &str->next;
7779                 } else {
7780                         *exparg.lastp = NULL;
7781                         *savelastp = sp = expsort(*savelastp);
7782                         while (sp->next != NULL)
7783                                 sp = sp->next;
7784                         exparg.lastp = &sp->next;
7785                 }
7786                 str = str->next;
7787         }
7788 }
7789 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7790
7791 /*
7792  * Perform variable substitution and command substitution on an argument,
7793  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7794  * perform splitting and file name expansion.  When arglist is NULL, perform
7795  * here document expansion.
7796  */
7797 static void
7798 expandarg(union node *arg, struct arglist *arglist, int flag)
7799 {
7800         struct strlist *sp;
7801         char *p;
7802
7803         argbackq = arg->narg.backquote;
7804         STARTSTACKSTR(expdest);
7805         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7806         argstr(arg->narg.text, flag);
7807         p = _STPUTC('\0', expdest);
7808         expdest = p - 1;
7809         if (arglist == NULL) {
7810                 /* here document expanded */
7811                 goto out;
7812         }
7813         p = grabstackstr(p);
7814         TRACE(("expandarg: p:'%s'\n", p));
7815         exparg.lastp = &exparg.list;
7816         /*
7817          * TODO - EXP_REDIR
7818          */
7819         if (flag & EXP_FULL) {
7820                 ifsbreakup(p, &exparg);
7821                 *exparg.lastp = NULL;
7822                 exparg.lastp = &exparg.list;
7823                 expandmeta(exparg.list /*, flag*/);
7824         } else {
7825                 sp = stzalloc(sizeof(*sp));
7826                 sp->text = p;
7827                 *exparg.lastp = sp;
7828                 exparg.lastp = &sp->next;
7829         }
7830         *exparg.lastp = NULL;
7831         if (exparg.list) {
7832                 *arglist->lastp = exparg.list;
7833                 arglist->lastp = exparg.lastp;
7834         }
7835
7836  out:
7837         ifsfree();
7838 }
7839
7840 /*
7841  * Expand shell variables and backquotes inside a here document.
7842  */
7843 static void
7844 expandhere(union node *arg, int fd)
7845 {
7846         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7847         full_write(fd, stackblock(), expdest - (char *)stackblock());
7848 }
7849
7850 /*
7851  * Returns true if the pattern matches the string.
7852  */
7853 static int
7854 patmatch(char *pattern, const char *string)
7855 {
7856         char *p = preglob(pattern, 0);
7857         int r = pmatch(p, string);
7858         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7859         return r;
7860 }
7861
7862 /*
7863  * See if a pattern matches in a case statement.
7864  */
7865 static int
7866 casematch(union node *pattern, char *val)
7867 {
7868         struct stackmark smark;
7869         int result;
7870
7871         setstackmark(&smark);
7872         argbackq = pattern->narg.backquote;
7873         STARTSTACKSTR(expdest);
7874         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7875         STACKSTRNUL(expdest);
7876         ifsfree();
7877         result = patmatch(stackblock(), val);
7878         popstackmark(&smark);
7879         return result;
7880 }
7881
7882
7883 /* ============ find_command */
7884
7885 struct builtincmd {
7886         const char *name;
7887         int (*builtin)(int, char **) FAST_FUNC;
7888         /* unsigned flags; */
7889 };
7890 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7891 /* "regular" builtins always take precedence over commands,
7892  * regardless of PATH=....%builtin... position */
7893 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7894 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7895
7896 struct cmdentry {
7897         smallint cmdtype;       /* CMDxxx */
7898         union param {
7899                 int index;
7900                 /* index >= 0 for commands without path (slashes) */
7901                 /* (TODO: what exactly does the value mean? PATH position?) */
7902                 /* index == -1 for commands with slashes */
7903                 /* index == (-2 - applet_no) for NOFORK applets */
7904                 const struct builtincmd *cmd;
7905                 struct funcnode *func;
7906         } u;
7907 };
7908 /* values of cmdtype */
7909 #define CMDUNKNOWN      -1      /* no entry in table for command */
7910 #define CMDNORMAL       0       /* command is an executable program */
7911 #define CMDFUNCTION     1       /* command is a shell function */
7912 #define CMDBUILTIN      2       /* command is a shell builtin */
7913
7914 /* action to find_command() */
7915 #define DO_ERR          0x01    /* prints errors */
7916 #define DO_ABS          0x02    /* checks absolute paths */
7917 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7918 #define DO_ALTPATH      0x08    /* using alternate path */
7919 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7920
7921 static void find_command(char *, struct cmdentry *, int, const char *);
7922
7923
7924 /* ============ Hashing commands */
7925
7926 /*
7927  * When commands are first encountered, they are entered in a hash table.
7928  * This ensures that a full path search will not have to be done for them
7929  * on each invocation.
7930  *
7931  * We should investigate converting to a linear search, even though that
7932  * would make the command name "hash" a misnomer.
7933  */
7934
7935 struct tblentry {
7936         struct tblentry *next;  /* next entry in hash chain */
7937         union param param;      /* definition of builtin function */
7938         smallint cmdtype;       /* CMDxxx */
7939         char rehash;            /* if set, cd done since entry created */
7940         char cmdname[1];        /* name of command */
7941 };
7942
7943 static struct tblentry **cmdtable;
7944 #define INIT_G_cmdtable() do { \
7945         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7946 } while (0)
7947
7948 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7949
7950
7951 static void
7952 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7953 {
7954 #if ENABLE_FEATURE_SH_STANDALONE
7955         if (applet_no >= 0) {
7956                 if (APPLET_IS_NOEXEC(applet_no)) {
7957                         clearenv();
7958                         while (*envp)
7959                                 putenv(*envp++);
7960                         popredir(/*drop:*/ 1);
7961                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7962                 }
7963                 /* re-exec ourselves with the new arguments */
7964                 execve(bb_busybox_exec_path, argv, envp);
7965                 /* If they called chroot or otherwise made the binary no longer
7966                  * executable, fall through */
7967         }
7968 #endif
7969
7970  repeat:
7971 #ifdef SYSV
7972         do {
7973                 execve(cmd, argv, envp);
7974         } while (errno == EINTR);
7975 #else
7976         execve(cmd, argv, envp);
7977 #endif
7978         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7979                 /* Run "cmd" as a shell script:
7980                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7981                  * "If the execve() function fails with ENOEXEC, the shell
7982                  * shall execute a command equivalent to having a shell invoked
7983                  * with the command name as its first operand,
7984                  * with any remaining arguments passed to the new shell"
7985                  *
7986                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7987                  * just call ourselves.
7988                  *
7989                  * Note that bash reads ~80 chars of the file, and if it sees
7990                  * a zero byte before it sees newline, it doesn't try to
7991                  * interpret it, but fails with "cannot execute binary file"
7992                  * message and exit code 126. For one, this prevents attempts
7993                  * to interpret foreign ELF binaries as shell scripts.
7994                  */
7995                 argv[0] = (char*) cmd;
7996                 cmd = bb_busybox_exec_path;
7997                 /* NB: this is only possible because all callers of shellexec()
7998                  * ensure that the argv[-1] slot exists!
7999                  */
8000                 argv--;
8001                 argv[0] = (char*) "ash";
8002                 goto repeat;
8003         }
8004 }
8005
8006 /*
8007  * Exec a program.  Never returns.  If you change this routine, you may
8008  * have to change the find_command routine as well.
8009  * argv[-1] must exist and be writable! See tryexec() for why.
8010  */
8011 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8012 static void shellexec(char *prog, char **argv, const char *path, int idx)
8013 {
8014         char *cmdname;
8015         int e;
8016         char **envp;
8017         int exerrno;
8018         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8019
8020         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8021         if (strchr(prog, '/') != NULL
8022 #if ENABLE_FEATURE_SH_STANDALONE
8023          || (applet_no = find_applet_by_name(prog)) >= 0
8024 #endif
8025         ) {
8026                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8027                 if (applet_no >= 0) {
8028                         /* We tried execing ourself, but it didn't work.
8029                          * Maybe /proc/self/exe doesn't exist?
8030                          * Try $PATH search.
8031                          */
8032                         goto try_PATH;
8033                 }
8034                 e = errno;
8035         } else {
8036  try_PATH:
8037                 e = ENOENT;
8038                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8039                         if (--idx < 0 && pathopt == NULL) {
8040                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8041                                 if (errno != ENOENT && errno != ENOTDIR)
8042                                         e = errno;
8043                         }
8044                         stunalloc(cmdname);
8045                 }
8046         }
8047
8048         /* Map to POSIX errors */
8049         switch (e) {
8050         case EACCES:
8051                 exerrno = 126;
8052                 break;
8053         case ENOENT:
8054                 exerrno = 127;
8055                 break;
8056         default:
8057                 exerrno = 2;
8058                 break;
8059         }
8060         exitstatus = exerrno;
8061         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8062                 prog, e, suppress_int));
8063         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8064         /* NOTREACHED */
8065 }
8066
8067 static void
8068 printentry(struct tblentry *cmdp)
8069 {
8070         int idx;
8071         const char *path;
8072         char *name;
8073
8074         idx = cmdp->param.index;
8075         path = pathval();
8076         do {
8077                 name = path_advance(&path, cmdp->cmdname);
8078                 stunalloc(name);
8079         } while (--idx >= 0);
8080         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8081 }
8082
8083 /*
8084  * Clear out command entries.  The argument specifies the first entry in
8085  * PATH which has changed.
8086  */
8087 static void
8088 clearcmdentry(int firstchange)
8089 {
8090         struct tblentry **tblp;
8091         struct tblentry **pp;
8092         struct tblentry *cmdp;
8093
8094         INT_OFF;
8095         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8096                 pp = tblp;
8097                 while ((cmdp = *pp) != NULL) {
8098                         if ((cmdp->cmdtype == CMDNORMAL &&
8099                              cmdp->param.index >= firstchange)
8100                          || (cmdp->cmdtype == CMDBUILTIN &&
8101                              builtinloc >= firstchange)
8102                         ) {
8103                                 *pp = cmdp->next;
8104                                 free(cmdp);
8105                         } else {
8106                                 pp = &cmdp->next;
8107                         }
8108                 }
8109         }
8110         INT_ON;
8111 }
8112
8113 /*
8114  * Locate a command in the command hash table.  If "add" is nonzero,
8115  * add the command to the table if it is not already present.  The
8116  * variable "lastcmdentry" is set to point to the address of the link
8117  * pointing to the entry, so that delete_cmd_entry can delete the
8118  * entry.
8119  *
8120  * Interrupts must be off if called with add != 0.
8121  */
8122 static struct tblentry **lastcmdentry;
8123
8124 static struct tblentry *
8125 cmdlookup(const char *name, int add)
8126 {
8127         unsigned int hashval;
8128         const char *p;
8129         struct tblentry *cmdp;
8130         struct tblentry **pp;
8131
8132         p = name;
8133         hashval = (unsigned char)*p << 4;
8134         while (*p)
8135                 hashval += (unsigned char)*p++;
8136         hashval &= 0x7FFF;
8137         pp = &cmdtable[hashval % CMDTABLESIZE];
8138         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8139                 if (strcmp(cmdp->cmdname, name) == 0)
8140                         break;
8141                 pp = &cmdp->next;
8142         }
8143         if (add && cmdp == NULL) {
8144                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8145                                 + strlen(name)
8146                                 /* + 1 - already done because
8147                                  * tblentry::cmdname is char[1] */);
8148                 /*cmdp->next = NULL; - ckzalloc did it */
8149                 cmdp->cmdtype = CMDUNKNOWN;
8150                 strcpy(cmdp->cmdname, name);
8151         }
8152         lastcmdentry = pp;
8153         return cmdp;
8154 }
8155
8156 /*
8157  * Delete the command entry returned on the last lookup.
8158  */
8159 static void
8160 delete_cmd_entry(void)
8161 {
8162         struct tblentry *cmdp;
8163
8164         INT_OFF;
8165         cmdp = *lastcmdentry;
8166         *lastcmdentry = cmdp->next;
8167         if (cmdp->cmdtype == CMDFUNCTION)
8168                 freefunc(cmdp->param.func);
8169         free(cmdp);
8170         INT_ON;
8171 }
8172
8173 /*
8174  * Add a new command entry, replacing any existing command entry for
8175  * the same name - except special builtins.
8176  */
8177 static void
8178 addcmdentry(char *name, struct cmdentry *entry)
8179 {
8180         struct tblentry *cmdp;
8181
8182         cmdp = cmdlookup(name, 1);
8183         if (cmdp->cmdtype == CMDFUNCTION) {
8184                 freefunc(cmdp->param.func);
8185         }
8186         cmdp->cmdtype = entry->cmdtype;
8187         cmdp->param = entry->u;
8188         cmdp->rehash = 0;
8189 }
8190
8191 static int FAST_FUNC
8192 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8193 {
8194         struct tblentry **pp;
8195         struct tblentry *cmdp;
8196         int c;
8197         struct cmdentry entry;
8198         char *name;
8199
8200         if (nextopt("r") != '\0') {
8201                 clearcmdentry(0);
8202                 return 0;
8203         }
8204
8205         if (*argptr == NULL) {
8206                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8207                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8208                                 if (cmdp->cmdtype == CMDNORMAL)
8209                                         printentry(cmdp);
8210                         }
8211                 }
8212                 return 0;
8213         }
8214
8215         c = 0;
8216         while ((name = *argptr) != NULL) {
8217                 cmdp = cmdlookup(name, 0);
8218                 if (cmdp != NULL
8219                  && (cmdp->cmdtype == CMDNORMAL
8220                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8221                 ) {
8222                         delete_cmd_entry();
8223                 }
8224                 find_command(name, &entry, DO_ERR, pathval());
8225                 if (entry.cmdtype == CMDUNKNOWN)
8226                         c = 1;
8227                 argptr++;
8228         }
8229         return c;
8230 }
8231
8232 /*
8233  * Called when a cd is done.  Marks all commands so the next time they
8234  * are executed they will be rehashed.
8235  */
8236 static void
8237 hashcd(void)
8238 {
8239         struct tblentry **pp;
8240         struct tblentry *cmdp;
8241
8242         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8243                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8244                         if (cmdp->cmdtype == CMDNORMAL
8245                          || (cmdp->cmdtype == CMDBUILTIN
8246                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8247                              && builtinloc > 0)
8248                         ) {
8249                                 cmdp->rehash = 1;
8250                         }
8251                 }
8252         }
8253 }
8254
8255 /*
8256  * Fix command hash table when PATH changed.
8257  * Called before PATH is changed.  The argument is the new value of PATH;
8258  * pathval() still returns the old value at this point.
8259  * Called with interrupts off.
8260  */
8261 static void FAST_FUNC
8262 changepath(const char *new)
8263 {
8264         const char *old;
8265         int firstchange;
8266         int idx;
8267         int idx_bltin;
8268
8269         old = pathval();
8270         firstchange = 9999;     /* assume no change */
8271         idx = 0;
8272         idx_bltin = -1;
8273         for (;;) {
8274                 if (*old != *new) {
8275                         firstchange = idx;
8276                         if ((*old == '\0' && *new == ':')
8277                          || (*old == ':' && *new == '\0')
8278                         ) {
8279                                 firstchange++;
8280                         }
8281                         old = new;      /* ignore subsequent differences */
8282                 }
8283                 if (*new == '\0')
8284                         break;
8285                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8286                         idx_bltin = idx;
8287                 if (*new == ':')
8288                         idx++;
8289                 new++;
8290                 old++;
8291         }
8292         if (builtinloc < 0 && idx_bltin >= 0)
8293                 builtinloc = idx_bltin;             /* zap builtins */
8294         if (builtinloc >= 0 && idx_bltin < 0)
8295                 firstchange = 0;
8296         clearcmdentry(firstchange);
8297         builtinloc = idx_bltin;
8298 }
8299 enum {
8300         TEOF,
8301         TNL,
8302         TREDIR,
8303         TWORD,
8304         TSEMI,
8305         TBACKGND,
8306         TAND,
8307         TOR,
8308         TPIPE,
8309         TLP,
8310         TRP,
8311         TENDCASE,
8312         TENDBQUOTE,
8313         TNOT,
8314         TCASE,
8315         TDO,
8316         TDONE,
8317         TELIF,
8318         TELSE,
8319         TESAC,
8320         TFI,
8321         TFOR,
8322 #if BASH_FUNCTION
8323         TFUNCTION,
8324 #endif
8325         TIF,
8326         TIN,
8327         TTHEN,
8328         TUNTIL,
8329         TWHILE,
8330         TBEGIN,
8331         TEND
8332 };
8333 typedef smallint token_id_t;
8334
8335 /* Nth bit indicates if token marks the end of a list */
8336 enum {
8337         tokendlist = 0
8338         /*  0 */ | (1u << TEOF)
8339         /*  1 */ | (0u << TNL)
8340         /*  2 */ | (0u << TREDIR)
8341         /*  3 */ | (0u << TWORD)
8342         /*  4 */ | (0u << TSEMI)
8343         /*  5 */ | (0u << TBACKGND)
8344         /*  6 */ | (0u << TAND)
8345         /*  7 */ | (0u << TOR)
8346         /*  8 */ | (0u << TPIPE)
8347         /*  9 */ | (0u << TLP)
8348         /* 10 */ | (1u << TRP)
8349         /* 11 */ | (1u << TENDCASE)
8350         /* 12 */ | (1u << TENDBQUOTE)
8351         /* 13 */ | (0u << TNOT)
8352         /* 14 */ | (0u << TCASE)
8353         /* 15 */ | (1u << TDO)
8354         /* 16 */ | (1u << TDONE)
8355         /* 17 */ | (1u << TELIF)
8356         /* 18 */ | (1u << TELSE)
8357         /* 19 */ | (1u << TESAC)
8358         /* 20 */ | (1u << TFI)
8359         /* 21 */ | (0u << TFOR)
8360 #if BASH_FUNCTION
8361         /* 22 */ | (0u << TFUNCTION)
8362 #endif
8363         /* 23 */ | (0u << TIF)
8364         /* 24 */ | (0u << TIN)
8365         /* 25 */ | (1u << TTHEN)
8366         /* 26 */ | (0u << TUNTIL)
8367         /* 27 */ | (0u << TWHILE)
8368         /* 28 */ | (0u << TBEGIN)
8369         /* 29 */ | (1u << TEND)
8370         , /* thus far 29 bits used */
8371 };
8372
8373 static const char *const tokname_array[] = {
8374         "end of file",
8375         "newline",
8376         "redirection",
8377         "word",
8378         ";",
8379         "&",
8380         "&&",
8381         "||",
8382         "|",
8383         "(",
8384         ")",
8385         ";;",
8386         "`",
8387 #define KWDOFFSET 13
8388         /* the following are keywords */
8389         "!",
8390         "case",
8391         "do",
8392         "done",
8393         "elif",
8394         "else",
8395         "esac",
8396         "fi",
8397         "for",
8398 #if BASH_FUNCTION
8399         "function",
8400 #endif
8401         "if",
8402         "in",
8403         "then",
8404         "until",
8405         "while",
8406         "{",
8407         "}",
8408 };
8409
8410 /* Wrapper around strcmp for qsort/bsearch/... */
8411 static int
8412 pstrcmp(const void *a, const void *b)
8413 {
8414         return strcmp((char*)a, *(char**)b);
8415 }
8416
8417 static const char *const *
8418 findkwd(const char *s)
8419 {
8420         return bsearch(s, tokname_array + KWDOFFSET,
8421                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8422                         sizeof(tokname_array[0]), pstrcmp);
8423 }
8424
8425 /*
8426  * Locate and print what a word is...
8427  */
8428 static int
8429 describe_command(char *command, const char *path, int describe_command_verbose)
8430 {
8431         struct cmdentry entry;
8432 #if ENABLE_ASH_ALIAS
8433         const struct alias *ap;
8434 #endif
8435
8436         path = path ? path : pathval();
8437
8438         if (describe_command_verbose) {
8439                 out1str(command);
8440         }
8441
8442         /* First look at the keywords */
8443         if (findkwd(command)) {
8444                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8445                 goto out;
8446         }
8447
8448 #if ENABLE_ASH_ALIAS
8449         /* Then look at the aliases */
8450         ap = lookupalias(command, 0);
8451         if (ap != NULL) {
8452                 if (!describe_command_verbose) {
8453                         out1str("alias ");
8454                         printalias(ap);
8455                         return 0;
8456                 }
8457                 out1fmt(" is an alias for %s", ap->val);
8458                 goto out;
8459         }
8460 #endif
8461         /* Brute force */
8462         find_command(command, &entry, DO_ABS, path);
8463
8464         switch (entry.cmdtype) {
8465         case CMDNORMAL: {
8466                 int j = entry.u.index;
8467                 char *p;
8468                 if (j < 0) {
8469                         p = command;
8470                 } else {
8471                         do {
8472                                 p = path_advance(&path, command);
8473                                 stunalloc(p);
8474                         } while (--j >= 0);
8475                 }
8476                 if (describe_command_verbose) {
8477                         out1fmt(" is %s", p);
8478                 } else {
8479                         out1str(p);
8480                 }
8481                 break;
8482         }
8483
8484         case CMDFUNCTION:
8485                 if (describe_command_verbose) {
8486                         out1str(" is a shell function");
8487                 } else {
8488                         out1str(command);
8489                 }
8490                 break;
8491
8492         case CMDBUILTIN:
8493                 if (describe_command_verbose) {
8494                         out1fmt(" is a %sshell builtin",
8495                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8496                                         "special " : nullstr
8497                         );
8498                 } else {
8499                         out1str(command);
8500                 }
8501                 break;
8502
8503         default:
8504                 if (describe_command_verbose) {
8505                         out1str(": not found\n");
8506                 }
8507                 return 127;
8508         }
8509  out:
8510         out1str("\n");
8511         return 0;
8512 }
8513
8514 static int FAST_FUNC
8515 typecmd(int argc UNUSED_PARAM, char **argv)
8516 {
8517         int i = 1;
8518         int err = 0;
8519         int verbose = 1;
8520
8521         /* type -p ... ? (we don't bother checking for 'p') */
8522         if (argv[1] && argv[1][0] == '-') {
8523                 i++;
8524                 verbose = 0;
8525         }
8526         while (argv[i]) {
8527                 err |= describe_command(argv[i++], NULL, verbose);
8528         }
8529         return err;
8530 }
8531
8532 #if ENABLE_ASH_CMDCMD
8533 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8534 static char **
8535 parse_command_args(char **argv, const char **path)
8536 {
8537         char *cp, c;
8538
8539         for (;;) {
8540                 cp = *++argv;
8541                 if (!cp)
8542                         return NULL;
8543                 if (*cp++ != '-')
8544                         break;
8545                 c = *cp++;
8546                 if (!c)
8547                         break;
8548                 if (c == '-' && !*cp) {
8549                         if (!*++argv)
8550                                 return NULL;
8551                         break;
8552                 }
8553                 do {
8554                         switch (c) {
8555                         case 'p':
8556                                 *path = bb_default_path;
8557                                 break;
8558                         default:
8559                                 /* run 'typecmd' for other options */
8560                                 return NULL;
8561                         }
8562                         c = *cp++;
8563                 } while (c);
8564         }
8565         return argv;
8566 }
8567
8568 static int FAST_FUNC
8569 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8570 {
8571         char *cmd;
8572         int c;
8573         enum {
8574                 VERIFY_BRIEF = 1,
8575                 VERIFY_VERBOSE = 2,
8576         } verify = 0;
8577         const char *path = NULL;
8578
8579         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8580          * never reaches this function.
8581          */
8582
8583         while ((c = nextopt("pvV")) != '\0')
8584                 if (c == 'V')
8585                         verify |= VERIFY_VERBOSE;
8586                 else if (c == 'v')
8587                         /*verify |= VERIFY_BRIEF*/;
8588 #if DEBUG
8589                 else if (c != 'p')
8590                         abort();
8591 #endif
8592                 else
8593                         path = bb_default_path;
8594
8595         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8596         cmd = *argptr;
8597         if (/*verify && */ cmd)
8598                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8599
8600         return 0;
8601 }
8602 #endif
8603
8604
8605 /*static int funcblocksize;     // size of structures in function */
8606 /*static int funcstringsize;    // size of strings in node */
8607 static void *funcblock;         /* block to allocate function from */
8608 static char *funcstring_end;    /* end of block to allocate strings from */
8609
8610 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8611         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8612         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8613         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8614         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8615         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8616         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8617         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8618         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8619         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8620         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8621         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8622         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8623         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8624         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8625         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8626         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8627         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8628 #if BASH_REDIR_OUTPUT
8629         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8630 #endif
8631         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8632         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8633         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8634         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8635         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8636         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8637         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8638         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8639         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8640 };
8641
8642 static int calcsize(int funcblocksize, union node *n);
8643
8644 static int
8645 sizenodelist(int funcblocksize, struct nodelist *lp)
8646 {
8647         while (lp) {
8648                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8649                 funcblocksize = calcsize(funcblocksize, lp->n);
8650                 lp = lp->next;
8651         }
8652         return funcblocksize;
8653 }
8654
8655 static int
8656 calcsize(int funcblocksize, union node *n)
8657 {
8658         if (n == NULL)
8659                 return funcblocksize;
8660         funcblocksize += nodesize[n->type];
8661         switch (n->type) {
8662         case NCMD:
8663                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8664                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8665                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8666                 break;
8667         case NPIPE:
8668                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8669                 break;
8670         case NREDIR:
8671         case NBACKGND:
8672         case NSUBSHELL:
8673                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8674                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8675                 break;
8676         case NAND:
8677         case NOR:
8678         case NSEMI:
8679         case NWHILE:
8680         case NUNTIL:
8681                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8682                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8683                 break;
8684         case NIF:
8685                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8686                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8687                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8688                 break;
8689         case NFOR:
8690                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8691                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8692                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8693                 break;
8694         case NCASE:
8695                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8696                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8697                 break;
8698         case NCLIST:
8699                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8700                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8701                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8702                 break;
8703         case NDEFUN:
8704                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8705                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8706                 break;
8707         case NARG:
8708                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8709                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8710                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8711                 break;
8712         case NTO:
8713 #if BASH_REDIR_OUTPUT
8714         case NTO2:
8715 #endif
8716         case NCLOBBER:
8717         case NFROM:
8718         case NFROMTO:
8719         case NAPPEND:
8720                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8721                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8722                 break;
8723         case NTOFD:
8724         case NFROMFD:
8725                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8726                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8727         break;
8728         case NHERE:
8729         case NXHERE:
8730                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8731                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8732                 break;
8733         case NNOT:
8734                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8735                 break;
8736         };
8737         return funcblocksize;
8738 }
8739
8740 static char *
8741 nodeckstrdup(char *s)
8742 {
8743         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8744         return strcpy(funcstring_end, s);
8745 }
8746
8747 static union node *copynode(union node *);
8748
8749 static struct nodelist *
8750 copynodelist(struct nodelist *lp)
8751 {
8752         struct nodelist *start;
8753         struct nodelist **lpp;
8754
8755         lpp = &start;
8756         while (lp) {
8757                 *lpp = funcblock;
8758                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8759                 (*lpp)->n = copynode(lp->n);
8760                 lp = lp->next;
8761                 lpp = &(*lpp)->next;
8762         }
8763         *lpp = NULL;
8764         return start;
8765 }
8766
8767 static union node *
8768 copynode(union node *n)
8769 {
8770         union node *new;
8771
8772         if (n == NULL)
8773                 return NULL;
8774         new = funcblock;
8775         funcblock = (char *) funcblock + nodesize[n->type];
8776
8777         switch (n->type) {
8778         case NCMD:
8779                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8780                 new->ncmd.args = copynode(n->ncmd.args);
8781                 new->ncmd.assign = copynode(n->ncmd.assign);
8782                 new->ncmd.linno = n->ncmd.linno;
8783                 break;
8784         case NPIPE:
8785                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8786                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8787                 break;
8788         case NREDIR:
8789         case NBACKGND:
8790         case NSUBSHELL:
8791                 new->nredir.redirect = copynode(n->nredir.redirect);
8792                 new->nredir.n = copynode(n->nredir.n);
8793                 new->nredir.linno = n->nredir.linno;
8794                 break;
8795         case NAND:
8796         case NOR:
8797         case NSEMI:
8798         case NWHILE:
8799         case NUNTIL:
8800                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8801                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8802                 break;
8803         case NIF:
8804                 new->nif.elsepart = copynode(n->nif.elsepart);
8805                 new->nif.ifpart = copynode(n->nif.ifpart);
8806                 new->nif.test = copynode(n->nif.test);
8807                 break;
8808         case NFOR:
8809                 new->nfor.var = nodeckstrdup(n->nfor.var);
8810                 new->nfor.body = copynode(n->nfor.body);
8811                 new->nfor.args = copynode(n->nfor.args);
8812                 new->nfor.linno = n->nfor.linno;
8813                 break;
8814         case NCASE:
8815                 new->ncase.cases = copynode(n->ncase.cases);
8816                 new->ncase.expr = copynode(n->ncase.expr);
8817                 new->ncase.linno = n->ncase.linno;
8818                 break;
8819         case NCLIST:
8820                 new->nclist.body = copynode(n->nclist.body);
8821                 new->nclist.pattern = copynode(n->nclist.pattern);
8822                 new->nclist.next = copynode(n->nclist.next);
8823                 break;
8824         case NDEFUN:
8825                 new->ndefun.body = copynode(n->ndefun.body);
8826                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8827                 new->ndefun.linno = n->ndefun.linno;
8828                 break;
8829         case NARG:
8830                 new->narg.backquote = copynodelist(n->narg.backquote);
8831                 new->narg.text = nodeckstrdup(n->narg.text);
8832                 new->narg.next = copynode(n->narg.next);
8833                 break;
8834         case NTO:
8835 #if BASH_REDIR_OUTPUT
8836         case NTO2:
8837 #endif
8838         case NCLOBBER:
8839         case NFROM:
8840         case NFROMTO:
8841         case NAPPEND:
8842                 new->nfile.fname = copynode(n->nfile.fname);
8843                 new->nfile.fd = n->nfile.fd;
8844                 new->nfile.next = copynode(n->nfile.next);
8845                 break;
8846         case NTOFD:
8847         case NFROMFD:
8848                 new->ndup.vname = copynode(n->ndup.vname);
8849                 new->ndup.dupfd = n->ndup.dupfd;
8850                 new->ndup.fd = n->ndup.fd;
8851                 new->ndup.next = copynode(n->ndup.next);
8852                 break;
8853         case NHERE:
8854         case NXHERE:
8855                 new->nhere.doc = copynode(n->nhere.doc);
8856                 new->nhere.fd = n->nhere.fd;
8857                 new->nhere.next = copynode(n->nhere.next);
8858                 break;
8859         case NNOT:
8860                 new->nnot.com = copynode(n->nnot.com);
8861                 break;
8862         };
8863         new->type = n->type;
8864         return new;
8865 }
8866
8867 /*
8868  * Make a copy of a parse tree.
8869  */
8870 static struct funcnode *
8871 copyfunc(union node *n)
8872 {
8873         struct funcnode *f;
8874         size_t blocksize;
8875
8876         /*funcstringsize = 0;*/
8877         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8878         f = ckzalloc(blocksize /* + funcstringsize */);
8879         funcblock = (char *) f + offsetof(struct funcnode, n);
8880         funcstring_end = (char *) f + blocksize;
8881         copynode(n);
8882         /* f->count = 0; - ckzalloc did it */
8883         return f;
8884 }
8885
8886 /*
8887  * Define a shell function.
8888  */
8889 static void
8890 defun(union node *func)
8891 {
8892         struct cmdentry entry;
8893
8894         INT_OFF;
8895         entry.cmdtype = CMDFUNCTION;
8896         entry.u.func = copyfunc(func);
8897         addcmdentry(func->ndefun.text, &entry);
8898         INT_ON;
8899 }
8900
8901 /* Reasons for skipping commands (see comment on breakcmd routine) */
8902 #define SKIPBREAK      (1 << 0)
8903 #define SKIPCONT       (1 << 1)
8904 #define SKIPFUNC       (1 << 2)
8905 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8906 static int skipcount;           /* number of levels to skip */
8907 static int loopnest;            /* current loop nesting level */
8908 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8909
8910 /* Forward decl way out to parsing code - dotrap needs it */
8911 static int evalstring(char *s, int flags);
8912
8913 /* Called to execute a trap.
8914  * Single callsite - at the end of evaltree().
8915  * If we return non-zero, evaltree raises EXEXIT exception.
8916  *
8917  * Perhaps we should avoid entering new trap handlers
8918  * while we are executing a trap handler. [is it a TODO?]
8919  */
8920 static void
8921 dotrap(void)
8922 {
8923         uint8_t *g;
8924         int sig;
8925         uint8_t last_status;
8926
8927         if (!pending_sig)
8928                 return;
8929
8930         last_status = exitstatus;
8931         pending_sig = 0;
8932         barrier();
8933
8934         TRACE(("dotrap entered\n"));
8935         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8936                 char *p;
8937
8938                 if (!*g)
8939                         continue;
8940
8941                 if (evalskip) {
8942                         pending_sig = sig;
8943                         break;
8944                 }
8945
8946                 p = trap[sig];
8947                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8948                  * don't upset it by resetting gotsig[SIGINT-1] */
8949                 if (sig == SIGINT && !p)
8950                         continue;
8951
8952                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8953                 *g = 0;
8954                 if (!p)
8955                         continue;
8956                 evalstring(p, 0);
8957         }
8958         exitstatus = last_status;
8959         TRACE(("dotrap returns\n"));
8960 }
8961
8962 /* forward declarations - evaluation is fairly recursive business... */
8963 static int evalloop(union node *, int);
8964 static int evalfor(union node *, int);
8965 static int evalcase(union node *, int);
8966 static int evalsubshell(union node *, int);
8967 static void expredir(union node *);
8968 static int evalpipe(union node *, int);
8969 static int evalcommand(union node *, int);
8970 static int evalbltin(const struct builtincmd *, int, char **, int);
8971 static void prehash(union node *);
8972
8973 /*
8974  * Evaluate a parse tree.  The value is left in the global variable
8975  * exitstatus.
8976  */
8977 static int
8978 evaltree(union node *n, int flags)
8979 {
8980         int checkexit = 0;
8981         int (*evalfn)(union node *, int);
8982         int status = 0;
8983
8984         if (n == NULL) {
8985                 TRACE(("evaltree(NULL) called\n"));
8986                 goto out;
8987         }
8988         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8989
8990         dotrap();
8991
8992         switch (n->type) {
8993         default:
8994 #if DEBUG
8995                 out1fmt("Node type = %d\n", n->type);
8996                 fflush_all();
8997                 break;
8998 #endif
8999         case NNOT:
9000                 status = !evaltree(n->nnot.com, EV_TESTED);
9001                 goto setstatus;
9002         case NREDIR:
9003                 errlinno = lineno = n->nredir.linno;
9004                 if (funcline)
9005                         lineno -= funcline - 1;
9006                 expredir(n->nredir.redirect);
9007                 pushredir(n->nredir.redirect);
9008                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9009                 if (!status) {
9010                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9011                 }
9012                 if (n->nredir.redirect)
9013                         popredir(/*drop:*/ 0);
9014                 goto setstatus;
9015         case NCMD:
9016                 evalfn = evalcommand;
9017  checkexit:
9018                 if (eflag && !(flags & EV_TESTED))
9019                         checkexit = ~0;
9020                 goto calleval;
9021         case NFOR:
9022                 evalfn = evalfor;
9023                 goto calleval;
9024         case NWHILE:
9025         case NUNTIL:
9026                 evalfn = evalloop;
9027                 goto calleval;
9028         case NSUBSHELL:
9029         case NBACKGND:
9030                 evalfn = evalsubshell;
9031                 goto checkexit;
9032         case NPIPE:
9033                 evalfn = evalpipe;
9034                 goto checkexit;
9035         case NCASE:
9036                 evalfn = evalcase;
9037                 goto calleval;
9038         case NAND:
9039         case NOR:
9040         case NSEMI: {
9041
9042 #if NAND + 1 != NOR
9043 #error NAND + 1 != NOR
9044 #endif
9045 #if NOR + 1 != NSEMI
9046 #error NOR + 1 != NSEMI
9047 #endif
9048                 unsigned is_or = n->type - NAND;
9049                 status = evaltree(
9050                         n->nbinary.ch1,
9051                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9052                 );
9053                 if ((!status) == is_or || evalskip)
9054                         break;
9055                 n = n->nbinary.ch2;
9056  evaln:
9057                 evalfn = evaltree;
9058  calleval:
9059                 status = evalfn(n, flags);
9060                 goto setstatus;
9061         }
9062         case NIF:
9063                 status = evaltree(n->nif.test, EV_TESTED);
9064                 if (evalskip)
9065                         break;
9066                 if (!status) {
9067                         n = n->nif.ifpart;
9068                         goto evaln;
9069                 }
9070                 if (n->nif.elsepart) {
9071                         n = n->nif.elsepart;
9072                         goto evaln;
9073                 }
9074                 status = 0;
9075                 goto setstatus;
9076         case NDEFUN:
9077                 defun(n);
9078                 /* Not necessary. To test it:
9079                  * "false; f() { qwerty; }; echo $?" should print 0.
9080                  */
9081                 /* status = 0; */
9082  setstatus:
9083                 exitstatus = status;
9084                 break;
9085         }
9086  out:
9087         /* Order of checks below is important:
9088          * signal handlers trigger before exit caused by "set -e".
9089          */
9090         dotrap();
9091
9092         if (checkexit & status)
9093                 raise_exception(EXEXIT);
9094         if (flags & EV_EXIT)
9095                 raise_exception(EXEXIT);
9096
9097         TRACE(("leaving evaltree (no interrupts)\n"));
9098         return exitstatus;
9099 }
9100
9101 static int
9102 skiploop(void)
9103 {
9104         int skip = evalskip;
9105
9106         switch (skip) {
9107         case 0:
9108                 break;
9109         case SKIPBREAK:
9110         case SKIPCONT:
9111                 if (--skipcount <= 0) {
9112                         evalskip = 0;
9113                         break;
9114                 }
9115                 skip = SKIPBREAK;
9116                 break;
9117         }
9118         return skip;
9119 }
9120
9121 static int
9122 evalloop(union node *n, int flags)
9123 {
9124         int skip;
9125         int status;
9126
9127         loopnest++;
9128         status = 0;
9129         flags &= EV_TESTED;
9130         do {
9131                 int i;
9132
9133                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9134                 skip = skiploop();
9135                 if (skip == SKIPFUNC)
9136                         status = i;
9137                 if (skip)
9138                         continue;
9139                 if (n->type != NWHILE)
9140                         i = !i;
9141                 if (i != 0)
9142                         break;
9143                 status = evaltree(n->nbinary.ch2, flags);
9144                 skip = skiploop();
9145         } while (!(skip & ~SKIPCONT));
9146         loopnest--;
9147
9148         return status;
9149 }
9150
9151 static int
9152 evalfor(union node *n, int flags)
9153 {
9154         struct arglist arglist;
9155         union node *argp;
9156         struct strlist *sp;
9157         struct stackmark smark;
9158         int status = 0;
9159
9160         errlinno = lineno = n->ncase.linno;
9161         if (funcline)
9162                 lineno -= funcline - 1;
9163
9164         setstackmark(&smark);
9165         arglist.list = NULL;
9166         arglist.lastp = &arglist.list;
9167         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9168                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9169         }
9170         *arglist.lastp = NULL;
9171
9172         loopnest++;
9173         flags &= EV_TESTED;
9174         for (sp = arglist.list; sp; sp = sp->next) {
9175                 setvar0(n->nfor.var, sp->text);
9176                 status = evaltree(n->nfor.body, flags);
9177                 if (skiploop() & ~SKIPCONT)
9178                         break;
9179         }
9180         loopnest--;
9181         popstackmark(&smark);
9182
9183         return status;
9184 }
9185
9186 static int
9187 evalcase(union node *n, int flags)
9188 {
9189         union node *cp;
9190         union node *patp;
9191         struct arglist arglist;
9192         struct stackmark smark;
9193         int status = 0;
9194
9195         errlinno = lineno = n->ncase.linno;
9196         if (funcline)
9197                 lineno -= funcline - 1;
9198
9199         setstackmark(&smark);
9200         arglist.list = NULL;
9201         arglist.lastp = &arglist.list;
9202         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9203         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9204                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9205                         if (casematch(patp, arglist.list->text)) {
9206                                 /* Ensure body is non-empty as otherwise
9207                                  * EV_EXIT may prevent us from setting the
9208                                  * exit status.
9209                                  */
9210                                 if (evalskip == 0 && cp->nclist.body) {
9211                                         status = evaltree(cp->nclist.body, flags);
9212                                 }
9213                                 goto out;
9214                         }
9215                 }
9216         }
9217  out:
9218         popstackmark(&smark);
9219
9220         return status;
9221 }
9222
9223 /*
9224  * Kick off a subshell to evaluate a tree.
9225  */
9226 static int
9227 evalsubshell(union node *n, int flags)
9228 {
9229         struct job *jp;
9230         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9231         int status;
9232
9233         errlinno = lineno = n->nredir.linno;
9234         if (funcline)
9235                 lineno -= funcline - 1;
9236
9237         expredir(n->nredir.redirect);
9238         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9239                 goto nofork;
9240         INT_OFF;
9241         if (backgnd == FORK_FG)
9242                 get_tty_state();
9243         jp = makejob(/*n,*/ 1);
9244         if (forkshell(jp, n, backgnd) == 0) {
9245                 /* child */
9246                 INT_ON;
9247                 flags |= EV_EXIT;
9248                 if (backgnd)
9249                         flags &= ~EV_TESTED;
9250  nofork:
9251                 redirect(n->nredir.redirect, 0);
9252                 evaltreenr(n->nredir.n, flags);
9253                 /* never returns */
9254         }
9255         /* parent */
9256         status = 0;
9257         if (backgnd == FORK_FG)
9258                 status = waitforjob(jp);
9259         INT_ON;
9260         return status;
9261 }
9262
9263 /*
9264  * Compute the names of the files in a redirection list.
9265  */
9266 static void fixredir(union node *, const char *, int);
9267 static void
9268 expredir(union node *n)
9269 {
9270         union node *redir;
9271
9272         for (redir = n; redir; redir = redir->nfile.next) {
9273                 struct arglist fn;
9274
9275                 fn.list = NULL;
9276                 fn.lastp = &fn.list;
9277                 switch (redir->type) {
9278                 case NFROMTO:
9279                 case NFROM:
9280                 case NTO:
9281 #if BASH_REDIR_OUTPUT
9282                 case NTO2:
9283 #endif
9284                 case NCLOBBER:
9285                 case NAPPEND:
9286                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9287                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9288 #if BASH_REDIR_OUTPUT
9289  store_expfname:
9290 #endif
9291 #if 0
9292 // By the design of stack allocator, the loop of this kind:
9293 //      while true; do while true; do break; done </dev/null; done
9294 // will look like a memory leak: ash plans to free expfname's
9295 // of "/dev/null" as soon as it finishes running the loop
9296 // (in this case, never).
9297 // This "fix" is wrong:
9298                         if (redir->nfile.expfname)
9299                                 stunalloc(redir->nfile.expfname);
9300 // It results in corrupted state of stacked allocations.
9301 #endif
9302                         redir->nfile.expfname = fn.list->text;
9303                         break;
9304                 case NFROMFD:
9305                 case NTOFD: /* >& */
9306                         if (redir->ndup.vname) {
9307                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9308                                 if (fn.list == NULL)
9309                                         ash_msg_and_raise_error("redir error");
9310 #if BASH_REDIR_OUTPUT
9311 //FIXME: we used expandarg with different args!
9312                                 if (!isdigit_str9(fn.list->text)) {
9313                                         /* >&file, not >&fd */
9314                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9315                                                 ash_msg_and_raise_error("redir error");
9316                                         redir->type = NTO2;
9317                                         goto store_expfname;
9318                                 }
9319 #endif
9320                                 fixredir(redir, fn.list->text, 1);
9321                         }
9322                         break;
9323                 }
9324         }
9325 }
9326
9327 /*
9328  * Evaluate a pipeline.  All the processes in the pipeline are children
9329  * of the process creating the pipeline.  (This differs from some versions
9330  * of the shell, which make the last process in a pipeline the parent
9331  * of all the rest.)
9332  */
9333 static int
9334 evalpipe(union node *n, int flags)
9335 {
9336         struct job *jp;
9337         struct nodelist *lp;
9338         int pipelen;
9339         int prevfd;
9340         int pip[2];
9341         int status = 0;
9342
9343         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9344         pipelen = 0;
9345         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9346                 pipelen++;
9347         flags |= EV_EXIT;
9348         INT_OFF;
9349         if (n->npipe.pipe_backgnd == 0)
9350                 get_tty_state();
9351         jp = makejob(/*n,*/ pipelen);
9352         prevfd = -1;
9353         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9354                 prehash(lp->n);
9355                 pip[1] = -1;
9356                 if (lp->next) {
9357                         if (pipe(pip) < 0) {
9358                                 close(prevfd);
9359                                 ash_msg_and_raise_perror("can't create pipe");
9360                         }
9361                 }
9362                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9363                         /* child */
9364                         INT_ON;
9365                         if (pip[1] >= 0) {
9366                                 close(pip[0]);
9367                         }
9368                         if (prevfd > 0) {
9369                                 dup2(prevfd, 0);
9370                                 close(prevfd);
9371                         }
9372                         if (pip[1] > 1) {
9373                                 dup2(pip[1], 1);
9374                                 close(pip[1]);
9375                         }
9376                         evaltreenr(lp->n, flags);
9377                         /* never returns */
9378                 }
9379                 /* parent */
9380                 if (prevfd >= 0)
9381                         close(prevfd);
9382                 prevfd = pip[0];
9383                 /* Don't want to trigger debugging */
9384                 if (pip[1] != -1)
9385                         close(pip[1]);
9386         }
9387         if (n->npipe.pipe_backgnd == 0) {
9388                 status = waitforjob(jp);
9389                 TRACE(("evalpipe:  job done exit status %d\n", status));
9390         }
9391         INT_ON;
9392
9393         return status;
9394 }
9395
9396 /*
9397  * Controls whether the shell is interactive or not.
9398  */
9399 static void
9400 setinteractive(int on)
9401 {
9402         static smallint is_interactive;
9403
9404         if (++on == is_interactive)
9405                 return;
9406         is_interactive = on;
9407         setsignal(SIGINT);
9408         setsignal(SIGQUIT);
9409         setsignal(SIGTERM);
9410 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9411         if (is_interactive > 1) {
9412                 /* Looks like they want an interactive shell */
9413                 static smallint did_banner;
9414
9415                 if (!did_banner) {
9416                         /* note: ash and hush share this string */
9417                         out1fmt("\n\n%s %s\n"
9418                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9419                                 "\n",
9420                                 bb_banner,
9421                                 "built-in shell (ash)"
9422                         );
9423                         did_banner = 1;
9424                 }
9425         }
9426 #endif
9427 }
9428
9429 static void
9430 optschanged(void)
9431 {
9432 #if DEBUG
9433         opentrace();
9434 #endif
9435         setinteractive(iflag);
9436         setjobctl(mflag);
9437 #if ENABLE_FEATURE_EDITING_VI
9438         if (viflag)
9439                 line_input_state->flags |= VI_MODE;
9440         else
9441                 line_input_state->flags &= ~VI_MODE;
9442 #else
9443         viflag = 0; /* forcibly keep the option off */
9444 #endif
9445 }
9446
9447 struct localvar_list {
9448         struct localvar_list *next;
9449         struct localvar *lv;
9450 };
9451
9452 static struct localvar_list *localvar_stack;
9453
9454 /*
9455  * Called after a function returns.
9456  * Interrupts must be off.
9457  */
9458 static void
9459 poplocalvars(int keep)
9460 {
9461         struct localvar_list *ll;
9462         struct localvar *lvp, *next;
9463         struct var *vp;
9464
9465         INT_OFF;
9466         ll = localvar_stack;
9467         localvar_stack = ll->next;
9468
9469         next = ll->lv;
9470         free(ll);
9471
9472         while ((lvp = next) != NULL) {
9473                 next = lvp->next;
9474                 vp = lvp->vp;
9475                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9476                 if (keep) {
9477                         int bits = VSTRFIXED;
9478
9479                         if (lvp->flags != VUNSET) {
9480                                 if (vp->var_text == lvp->text)
9481                                         bits |= VTEXTFIXED;
9482                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9483                                         free((char*)lvp->text);
9484                         }
9485
9486                         vp->flags &= ~bits;
9487                         vp->flags |= (lvp->flags & bits);
9488
9489                         if ((vp->flags &
9490                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9491                                 unsetvar(vp->var_text);
9492                 } else if (vp == NULL) {        /* $- saved */
9493                         memcpy(optlist, lvp->text, sizeof(optlist));
9494                         free((char*)lvp->text);
9495                         optschanged();
9496                 } else if (lvp->flags == VUNSET) {
9497                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9498                         unsetvar(vp->var_text);
9499                 } else {
9500                         if (vp->var_func)
9501                                 vp->var_func(var_end(lvp->text));
9502                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9503                                 free((char*)vp->var_text);
9504                         vp->flags = lvp->flags;
9505                         vp->var_text = lvp->text;
9506                 }
9507                 free(lvp);
9508         }
9509         INT_ON;
9510 }
9511
9512 /*
9513  * Create a new localvar environment.
9514  */
9515 static struct localvar_list *
9516 pushlocalvars(void)
9517 {
9518         struct localvar_list *ll;
9519
9520         INT_OFF;
9521         ll = ckzalloc(sizeof(*ll));
9522         /*ll->lv = NULL; - zalloc did it */
9523         ll->next = localvar_stack;
9524         localvar_stack = ll;
9525         INT_ON;
9526
9527         return ll->next;
9528 }
9529
9530 static void
9531 unwindlocalvars(struct localvar_list *stop)
9532 {
9533         while (localvar_stack != stop)
9534                 poplocalvars(0);
9535 }
9536
9537 static int
9538 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9539 {
9540         volatile struct shparam saveparam;
9541         struct jmploc *volatile savehandler;
9542         struct jmploc jmploc;
9543         int e;
9544         int savefuncline;
9545
9546         saveparam = shellparam;
9547         savefuncline = funcline;
9548         savehandler = exception_handler;
9549         e = setjmp(jmploc.loc);
9550         if (e) {
9551                 goto funcdone;
9552         }
9553         INT_OFF;
9554         exception_handler = &jmploc;
9555         shellparam.malloced = 0;
9556         func->count++;
9557         funcline = func->n.ndefun.linno;
9558         INT_ON;
9559         shellparam.nparam = argc - 1;
9560         shellparam.p = argv + 1;
9561 #if ENABLE_ASH_GETOPTS
9562         shellparam.optind = 1;
9563         shellparam.optoff = -1;
9564 #endif
9565         pushlocalvars();
9566         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9567         poplocalvars(0);
9568  funcdone:
9569         INT_OFF;
9570         funcline = savefuncline;
9571         freefunc(func);
9572         freeparam(&shellparam);
9573         shellparam = saveparam;
9574         exception_handler = savehandler;
9575         INT_ON;
9576         evalskip &= ~SKIPFUNC;
9577         return e;
9578 }
9579
9580 /*
9581  * Make a variable a local variable.  When a variable is made local, it's
9582  * value and flags are saved in a localvar structure.  The saved values
9583  * will be restored when the shell function returns.  We handle the name
9584  * "-" as a special case: it makes changes to "set +-options" local
9585  * (options will be restored on return from the function).
9586  */
9587 static void
9588 mklocal(char *name)
9589 {
9590         struct localvar *lvp;
9591         struct var **vpp;
9592         struct var *vp;
9593         char *eq = strchr(name, '=');
9594
9595         INT_OFF;
9596         /* Cater for duplicate "local". Examples:
9597          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9598          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9599          */
9600         lvp = localvar_stack->lv;
9601         while (lvp) {
9602                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9603                         if (eq)
9604                                 setvareq(name, 0);
9605                         /* else:
9606                          * it's a duplicate "local VAR" declaration, do nothing
9607                          */
9608                         goto ret;
9609                 }
9610                 lvp = lvp->next;
9611         }
9612
9613         lvp = ckzalloc(sizeof(*lvp));
9614         if (LONE_DASH(name)) {
9615                 char *p;
9616                 p = ckmalloc(sizeof(optlist));
9617                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9618                 vp = NULL;
9619         } else {
9620                 vpp = hashvar(name);
9621                 vp = *findvar(vpp, name);
9622                 if (vp == NULL) {
9623                         /* variable did not exist yet */
9624                         if (eq)
9625                                 vp = setvareq(name, VSTRFIXED);
9626                         else
9627                                 vp = setvar(name, NULL, VSTRFIXED);
9628                         lvp->flags = VUNSET;
9629                 } else {
9630                         lvp->text = vp->var_text;
9631                         lvp->flags = vp->flags;
9632                         /* make sure neither "struct var" nor string gets freed
9633                          * during (un)setting:
9634                          */
9635                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9636                         if (eq)
9637                                 setvareq(name, 0);
9638                         else
9639                                 /* "local VAR" unsets VAR: */
9640                                 setvar0(name, NULL);
9641                 }
9642         }
9643         lvp->vp = vp;
9644         lvp->next = localvar_stack->lv;
9645         localvar_stack->lv = lvp;
9646  ret:
9647         INT_ON;
9648 }
9649
9650 /*
9651  * The "local" command.
9652  */
9653 static int FAST_FUNC
9654 localcmd(int argc UNUSED_PARAM, char **argv)
9655 {
9656         char *name;
9657
9658         if (!localvar_stack)
9659                 ash_msg_and_raise_error("not in a function");
9660
9661         argv = argptr;
9662         while ((name = *argv++) != NULL) {
9663                 mklocal(name);
9664         }
9665         return 0;
9666 }
9667
9668 static int FAST_FUNC
9669 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9670 {
9671         return 1;
9672 }
9673
9674 static int FAST_FUNC
9675 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9676 {
9677         return 0;
9678 }
9679
9680 static int FAST_FUNC
9681 execcmd(int argc UNUSED_PARAM, char **argv)
9682 {
9683         optionarg = NULL;
9684         while (nextopt("a:") != '\0')
9685                 /* nextopt() sets optionarg to "-a ARGV0" */;
9686
9687         argv = argptr;
9688         if (argv[0]) {
9689                 char *prog;
9690
9691                 iflag = 0;              /* exit on error */
9692                 mflag = 0;
9693                 optschanged();
9694                 /* We should set up signals for "exec CMD"
9695                  * the same way as for "CMD" without "exec".
9696                  * But optschanged->setinteractive->setsignal
9697                  * still thought we are a root shell. Therefore, for example,
9698                  * SIGQUIT is still set to IGN. Fix it:
9699                  */
9700                 shlvl++;
9701                 setsignal(SIGQUIT);
9702                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9703                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9704                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9705
9706                 prog = argv[0];
9707                 if (optionarg)
9708                         argv[0] = optionarg;
9709                 shellexec(prog, argv, pathval(), 0);
9710                 /* NOTREACHED */
9711         }
9712         return 0;
9713 }
9714
9715 /*
9716  * The return command.
9717  */
9718 static int FAST_FUNC
9719 returncmd(int argc UNUSED_PARAM, char **argv)
9720 {
9721         /*
9722          * If called outside a function, do what ksh does;
9723          * skip the rest of the file.
9724          */
9725         evalskip = SKIPFUNC;
9726         return argv[1] ? number(argv[1]) : exitstatus;
9727 }
9728
9729 /* Forward declarations for builtintab[] */
9730 static int breakcmd(int, char **) FAST_FUNC;
9731 static int dotcmd(int, char **) FAST_FUNC;
9732 static int evalcmd(int, char **, int) FAST_FUNC;
9733 static int exitcmd(int, char **) FAST_FUNC;
9734 static int exportcmd(int, char **) FAST_FUNC;
9735 #if ENABLE_ASH_GETOPTS
9736 static int getoptscmd(int, char **) FAST_FUNC;
9737 #endif
9738 #if ENABLE_ASH_HELP
9739 static int helpcmd(int, char **) FAST_FUNC;
9740 #endif
9741 #if MAX_HISTORY
9742 static int historycmd(int, char **) FAST_FUNC;
9743 #endif
9744 #if ENABLE_FEATURE_SH_MATH
9745 static int letcmd(int, char **) FAST_FUNC;
9746 #endif
9747 static int readcmd(int, char **) FAST_FUNC;
9748 static int setcmd(int, char **) FAST_FUNC;
9749 static int shiftcmd(int, char **) FAST_FUNC;
9750 static int timescmd(int, char **) FAST_FUNC;
9751 static int trapcmd(int, char **) FAST_FUNC;
9752 static int umaskcmd(int, char **) FAST_FUNC;
9753 static int unsetcmd(int, char **) FAST_FUNC;
9754 static int ulimitcmd(int, char **) FAST_FUNC;
9755
9756 #define BUILTIN_NOSPEC          "0"
9757 #define BUILTIN_SPECIAL         "1"
9758 #define BUILTIN_REGULAR         "2"
9759 #define BUILTIN_SPEC_REG        "3"
9760 #define BUILTIN_ASSIGN          "4"
9761 #define BUILTIN_SPEC_ASSG       "5"
9762 #define BUILTIN_REG_ASSG        "6"
9763 #define BUILTIN_SPEC_REG_ASSG   "7"
9764
9765 /* Stubs for calling non-FAST_FUNC's */
9766 #if ENABLE_ASH_ECHO
9767 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9768 #endif
9769 #if ENABLE_ASH_PRINTF
9770 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9771 #endif
9772 #if ENABLE_ASH_TEST || BASH_TEST2
9773 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9774 #endif
9775
9776 /* Keep these in proper order since it is searched via bsearch() */
9777 static const struct builtincmd builtintab[] = {
9778         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9779         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9780 #if ENABLE_ASH_TEST
9781         { BUILTIN_REGULAR       "["       , testcmd    },
9782 #endif
9783 #if BASH_TEST2
9784         { BUILTIN_REGULAR       "[["      , testcmd    },
9785 #endif
9786 #if ENABLE_ASH_ALIAS
9787         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9788 #endif
9789 #if JOBS
9790         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9791 #endif
9792         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9793         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9794         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9795 #if ENABLE_ASH_CMDCMD
9796         { BUILTIN_REGULAR       "command" , commandcmd },
9797 #endif
9798         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9799 #if ENABLE_ASH_ECHO
9800         { BUILTIN_REGULAR       "echo"    , echocmd    },
9801 #endif
9802         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9803         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9804         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9805         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9806         { BUILTIN_REGULAR       "false"   , falsecmd   },
9807 #if JOBS
9808         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9809 #endif
9810 #if ENABLE_ASH_GETOPTS
9811         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9812 #endif
9813         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9814 #if ENABLE_ASH_HELP
9815         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9816 #endif
9817 #if MAX_HISTORY
9818         { BUILTIN_NOSPEC        "history" , historycmd },
9819 #endif
9820 #if JOBS
9821         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9822         { BUILTIN_REGULAR       "kill"    , killcmd    },
9823 #endif
9824 #if ENABLE_FEATURE_SH_MATH
9825         { BUILTIN_NOSPEC        "let"     , letcmd     },
9826 #endif
9827         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9828 #if ENABLE_ASH_PRINTF
9829         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9830 #endif
9831         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9832         { BUILTIN_REGULAR       "read"    , readcmd    },
9833         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9834         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9835         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9836         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9837 #if BASH_SOURCE
9838         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9839 #endif
9840 #if ENABLE_ASH_TEST
9841         { BUILTIN_REGULAR       "test"    , testcmd    },
9842 #endif
9843         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9844         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9845         { BUILTIN_REGULAR       "true"    , truecmd    },
9846         { BUILTIN_NOSPEC        "type"    , typecmd    },
9847         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9848         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9849 #if ENABLE_ASH_ALIAS
9850         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9851 #endif
9852         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9853         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9854 };
9855
9856 /* Should match the above table! */
9857 #define COMMANDCMD (builtintab + \
9858         /* . : */       2 + \
9859         /* [ */         1 * ENABLE_ASH_TEST + \
9860         /* [[ */        1 * BASH_TEST2 + \
9861         /* alias */     1 * ENABLE_ASH_ALIAS + \
9862         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9863         /* break cd cddir  */   3)
9864 #define EVALCMD (COMMANDCMD + \
9865         /* command */   1 * ENABLE_ASH_CMDCMD + \
9866         /* continue */  1 + \
9867         /* echo */      1 * ENABLE_ASH_ECHO + \
9868         0)
9869 #define EXECCMD (EVALCMD + \
9870         /* eval */      1)
9871
9872 /*
9873  * Search the table of builtin commands.
9874  */
9875 static int
9876 pstrcmp1(const void *a, const void *b)
9877 {
9878         return strcmp((char*)a, *(char**)b + 1);
9879 }
9880 static struct builtincmd *
9881 find_builtin(const char *name)
9882 {
9883         struct builtincmd *bp;
9884
9885         bp = bsearch(
9886                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9887                 pstrcmp1
9888         );
9889         return bp;
9890 }
9891
9892 /*
9893  * Execute a simple command.
9894  */
9895 static int
9896 isassignment(const char *p)
9897 {
9898         const char *q = endofname(p);
9899         if (p == q)
9900                 return 0;
9901         return *q == '=';
9902 }
9903 static int FAST_FUNC
9904 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9905 {
9906         /* Preserve exitstatus of a previous possible redirection
9907          * as POSIX mandates */
9908         return back_exitstatus;
9909 }
9910 static int
9911 evalcommand(union node *cmd, int flags)
9912 {
9913         static const struct builtincmd null_bltin = {
9914                 "\0\0", bltincmd /* why three NULs? */
9915         };
9916         struct localvar_list *localvar_stop;
9917         struct redirtab *redir_stop;
9918         struct stackmark smark;
9919         union node *argp;
9920         struct arglist arglist;
9921         struct arglist varlist;
9922         char **argv;
9923         int argc;
9924         const struct strlist *sp;
9925         struct cmdentry cmdentry;
9926         struct job *jp;
9927         char *lastarg;
9928         const char *path;
9929         int spclbltin;
9930         int status;
9931         char **nargv;
9932         smallint cmd_is_exec;
9933
9934         errlinno = lineno = cmd->ncmd.linno;
9935         if (funcline)
9936                 lineno -= funcline - 1;
9937
9938         /* First expand the arguments. */
9939         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9940         setstackmark(&smark);
9941         localvar_stop = pushlocalvars();
9942         back_exitstatus = 0;
9943
9944         cmdentry.cmdtype = CMDBUILTIN;
9945         cmdentry.u.cmd = &null_bltin;
9946         varlist.lastp = &varlist.list;
9947         *varlist.lastp = NULL;
9948         arglist.lastp = &arglist.list;
9949         *arglist.lastp = NULL;
9950
9951         argc = 0;
9952         if (cmd->ncmd.args) {
9953                 struct builtincmd *bcmd;
9954                 smallint pseudovarflag;
9955
9956                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9957                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9958
9959                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9960                         struct strlist **spp;
9961
9962                         spp = arglist.lastp;
9963                         if (pseudovarflag && isassignment(argp->narg.text))
9964                                 expandarg(argp, &arglist, EXP_VARTILDE);
9965                         else
9966                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9967
9968                         for (sp = *spp; sp; sp = sp->next)
9969                                 argc++;
9970                 }
9971         }
9972
9973         /* Reserve one extra spot at the front for shellexec. */
9974         nargv = stalloc(sizeof(char *) * (argc + 2));
9975         argv = ++nargv;
9976         for (sp = arglist.list; sp; sp = sp->next) {
9977                 TRACE(("evalcommand arg: %s\n", sp->text));
9978                 *nargv++ = sp->text;
9979         }
9980         *nargv = NULL;
9981
9982         lastarg = NULL;
9983         if (iflag && funcline == 0 && argc > 0)
9984                 lastarg = nargv[-1];
9985
9986         expredir(cmd->ncmd.redirect);
9987         redir_stop = pushredir(cmd->ncmd.redirect);
9988         preverrout_fd = 2;
9989         if (BASH_XTRACEFD && xflag) {
9990                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9991                  * we do not emulate this. We only use its value.
9992                  */
9993                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9994                 if (xtracefd && is_number(xtracefd))
9995                         preverrout_fd = atoi(xtracefd);
9996
9997         }
9998         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9999
10000         path = vpath.var_text;
10001         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10002                 struct strlist **spp;
10003                 char *p;
10004
10005                 spp = varlist.lastp;
10006                 expandarg(argp, &varlist, EXP_VARTILDE);
10007
10008                 mklocal((*spp)->text);
10009
10010                 /*
10011                  * Modify the command lookup path, if a PATH= assignment
10012                  * is present
10013                  */
10014                 p = (*spp)->text;
10015                 if (varcmp(p, path) == 0)
10016                         path = p;
10017         }
10018
10019         /* Print the command if xflag is set. */
10020         if (xflag) {
10021                 const char *pfx = "";
10022
10023                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10024
10025                 sp = varlist.list;
10026                 while (sp) {
10027                         char *varval = sp->text;
10028                         char *eq = strchrnul(varval, '=');
10029                         if (*eq)
10030                                 eq++;
10031                         fdprintf(preverrout_fd, "%s%.*s%s",
10032                                 pfx,
10033                                 (int)(eq - varval), varval,
10034                                 maybe_single_quote(eq)
10035                         );
10036                         sp = sp->next;
10037                         pfx = " ";
10038                 }
10039
10040                 sp = arglist.list;
10041                 while (sp) {
10042                         fdprintf(preverrout_fd, "%s%s",
10043                                 pfx,
10044                                 /* always quote if matches reserved word: */
10045                                 findkwd(sp->text)
10046                                 ? single_quote(sp->text)
10047                                 : maybe_single_quote(sp->text)
10048                         );
10049                         sp = sp->next;
10050                         pfx = " ";
10051                 }
10052                 safe_write(preverrout_fd, "\n", 1);
10053         }
10054
10055         cmd_is_exec = 0;
10056         spclbltin = -1;
10057
10058         /* Now locate the command. */
10059         if (argc) {
10060                 int cmd_flag = DO_ERR;
10061 #if ENABLE_ASH_CMDCMD
10062                 const char *oldpath = path + 5;
10063 #endif
10064                 path += 5;
10065                 for (;;) {
10066                         find_command(argv[0], &cmdentry, cmd_flag, path);
10067                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10068                                 flush_stdout_stderr();
10069                                 status = 127;
10070                                 goto bail;
10071                         }
10072
10073                         /* implement bltin and command here */
10074                         if (cmdentry.cmdtype != CMDBUILTIN)
10075                                 break;
10076                         if (spclbltin < 0)
10077                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10078                         if (cmdentry.u.cmd == EXECCMD)
10079                                 cmd_is_exec = 1;
10080 #if ENABLE_ASH_CMDCMD
10081                         if (cmdentry.u.cmd == COMMANDCMD) {
10082                                 path = oldpath;
10083                                 nargv = parse_command_args(argv, &path);
10084                                 if (!nargv)
10085                                         break;
10086                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10087                                  * nargv => "PROG". path is updated if -p.
10088                                  */
10089                                 argc -= nargv - argv;
10090                                 argv = nargv;
10091                                 cmd_flag |= DO_NOFUNC;
10092                         } else
10093 #endif
10094                                 break;
10095                 }
10096         }
10097
10098         if (status) {
10099  bail:
10100                 exitstatus = status;
10101
10102                 /* We have a redirection error. */
10103                 if (spclbltin > 0)
10104                         raise_exception(EXERROR);
10105
10106                 goto out;
10107         }
10108
10109         /* Execute the command. */
10110         switch (cmdentry.cmdtype) {
10111         default: {
10112
10113 #if ENABLE_FEATURE_SH_STANDALONE \
10114  && ENABLE_FEATURE_SH_NOFORK \
10115  && NUM_APPLETS > 1
10116 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10117  *     around run_nofork_applet() call.
10118  * (2) Should this check also be done in forkshell()?
10119  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10120  */
10121                 /* find_command() encodes applet_no as (-2 - applet_no) */
10122                 int applet_no = (- cmdentry.u.index - 2);
10123                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10124                         char **sv_environ;
10125
10126                         INT_OFF;
10127                         sv_environ = environ;
10128                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10129                         /*
10130                          * Run <applet>_main().
10131                          * Signals (^C) can't interrupt here.
10132                          * Otherwise we can mangle stdio or malloc internal state.
10133                          * This makes applets which can run for a long time
10134                          * and/or wait for user input ineligible for NOFORK:
10135                          * for example, "yes" or "rm" (rm -i waits for input).
10136                          */
10137                         status = run_nofork_applet(applet_no, argv);
10138                         environ = sv_environ;
10139                         /*
10140                          * Try enabling NOFORK for "yes" applet.
10141                          * ^C _will_ stop it (write returns EINTR),
10142                          * but this causes stdout FILE to be stuck
10143                          * and needing clearerr(). What if other applets
10144                          * also can get EINTRs? Do we need to switch
10145                          * our signals to SA_RESTART?
10146                          */
10147                         /*clearerr(stdout);*/
10148                         INT_ON;
10149                         break;
10150                 }
10151 #endif
10152                 /* Can we avoid forking? For example, very last command
10153                  * in a script or a subshell does not need forking,
10154                  * we can just exec it.
10155                  */
10156                 if (!(flags & EV_EXIT) || may_have_traps) {
10157                         /* No, forking off a child is necessary */
10158                         INT_OFF;
10159                         get_tty_state();
10160                         jp = makejob(/*cmd,*/ 1);
10161                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10162                                 /* parent */
10163                                 status = waitforjob(jp);
10164                                 INT_ON;
10165                                 TRACE(("forked child exited with %d\n", status));
10166                                 break;
10167                         }
10168                         /* child */
10169                         FORCE_INT_ON;
10170                         /* fall through to exec'ing external program */
10171                 }
10172                 listsetvar(varlist.list, VEXPORT|VSTACK);
10173                 shellexec(argv[0], argv, path, cmdentry.u.index);
10174                 /* NOTREACHED */
10175         } /* default */
10176         case CMDBUILTIN:
10177                 if (spclbltin > 0 || argc == 0) {
10178                         poplocalvars(1);
10179                         if (cmd_is_exec && argc > 1)
10180                                 listsetvar(varlist.list, VEXPORT);
10181                 }
10182
10183                 /* Tight loop with builtins only:
10184                  * "while kill -0 $child; do true; done"
10185                  * will never exit even if $child died, unless we do this
10186                  * to reap the zombie and make kill detect that it's gone: */
10187                 dowait(DOWAIT_NONBLOCK, NULL);
10188
10189                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10190                         if (exception_type == EXERROR && spclbltin <= 0) {
10191                                 FORCE_INT_ON;
10192                                 goto readstatus;
10193                         }
10194  raise:
10195                         longjmp(exception_handler->loc, 1);
10196                 }
10197                 goto readstatus;
10198
10199         case CMDFUNCTION:
10200                 poplocalvars(1);
10201                 /* See above for the rationale */
10202                 dowait(DOWAIT_NONBLOCK, NULL);
10203                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10204                         goto raise;
10205  readstatus:
10206                 status = exitstatus;
10207                 break;
10208         } /* switch */
10209
10210  out:
10211         if (cmd->ncmd.redirect)
10212                 popredir(/*drop:*/ cmd_is_exec);
10213         unwindredir(redir_stop);
10214         unwindlocalvars(localvar_stop);
10215         if (lastarg) {
10216                 /* dsl: I think this is intended to be used to support
10217                  * '_' in 'vi' command mode during line editing...
10218                  * However I implemented that within libedit itself.
10219                  */
10220                 setvar0("_", lastarg);
10221         }
10222         popstackmark(&smark);
10223
10224         return status;
10225 }
10226
10227 static int
10228 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10229 {
10230         char *volatile savecmdname;
10231         struct jmploc *volatile savehandler;
10232         struct jmploc jmploc;
10233         int status;
10234         int i;
10235
10236         savecmdname = commandname;
10237         savehandler = exception_handler;
10238         i = setjmp(jmploc.loc);
10239         if (i)
10240                 goto cmddone;
10241         exception_handler = &jmploc;
10242         commandname = argv[0];
10243         argptr = argv + 1;
10244         optptr = NULL;                  /* initialize nextopt */
10245         if (cmd == EVALCMD)
10246                 status = evalcmd(argc, argv, flags);
10247         else
10248                 status = (*cmd->builtin)(argc, argv);
10249         flush_stdout_stderr();
10250         status |= ferror(stdout);
10251         exitstatus = status;
10252  cmddone:
10253         clearerr(stdout);
10254         commandname = savecmdname;
10255         exception_handler = savehandler;
10256
10257         return i;
10258 }
10259
10260 static int
10261 goodname(const char *p)
10262 {
10263         return endofname(p)[0] == '\0';
10264 }
10265
10266
10267 /*
10268  * Search for a command.  This is called before we fork so that the
10269  * location of the command will be available in the parent as well as
10270  * the child.  The check for "goodname" is an overly conservative
10271  * check that the name will not be subject to expansion.
10272  */
10273 static void
10274 prehash(union node *n)
10275 {
10276         struct cmdentry entry;
10277
10278         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10279                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10280 }
10281
10282
10283 /* ============ Builtin commands
10284  *
10285  * Builtin commands whose functions are closely tied to evaluation
10286  * are implemented here.
10287  */
10288
10289 /*
10290  * Handle break and continue commands.  Break, continue, and return are
10291  * all handled by setting the evalskip flag.  The evaluation routines
10292  * above all check this flag, and if it is set they start skipping
10293  * commands rather than executing them.  The variable skipcount is
10294  * the number of loops to break/continue, or the number of function
10295  * levels to return.  (The latter is always 1.)  It should probably
10296  * be an error to break out of more loops than exist, but it isn't
10297  * in the standard shell so we don't make it one here.
10298  */
10299 static int FAST_FUNC
10300 breakcmd(int argc UNUSED_PARAM, char **argv)
10301 {
10302         int n = argv[1] ? number(argv[1]) : 1;
10303
10304         if (n <= 0)
10305                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10306         if (n > loopnest)
10307                 n = loopnest;
10308         if (n > 0) {
10309                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10310                 skipcount = n;
10311         }
10312         return 0;
10313 }
10314
10315
10316 /*
10317  * This implements the input routines used by the parser.
10318  */
10319
10320 enum {
10321         INPUT_PUSH_FILE = 1,
10322         INPUT_NOFILE_OK = 2,
10323 };
10324
10325 static smallint checkkwd;
10326 /* values of checkkwd variable */
10327 #define CHKALIAS        0x1
10328 #define CHKKWD          0x2
10329 #define CHKNL           0x4
10330 #define CHKEOFMARK      0x8
10331
10332 /*
10333  * Push a string back onto the input at this current parsefile level.
10334  * We handle aliases this way.
10335  */
10336 #if !ENABLE_ASH_ALIAS
10337 #define pushstring(s, ap) pushstring(s)
10338 #endif
10339 static void
10340 pushstring(char *s, struct alias *ap)
10341 {
10342         struct strpush *sp;
10343         int len;
10344
10345         len = strlen(s);
10346         INT_OFF;
10347         if (g_parsefile->strpush) {
10348                 sp = ckzalloc(sizeof(*sp));
10349                 sp->prev = g_parsefile->strpush;
10350         } else {
10351                 sp = &(g_parsefile->basestrpush);
10352         }
10353         g_parsefile->strpush = sp;
10354         sp->prev_string = g_parsefile->next_to_pgetc;
10355         sp->prev_left_in_line = g_parsefile->left_in_line;
10356         sp->unget = g_parsefile->unget;
10357         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10358 #if ENABLE_ASH_ALIAS
10359         sp->ap = ap;
10360         if (ap) {
10361                 ap->flag |= ALIASINUSE;
10362                 sp->string = s;
10363         }
10364 #endif
10365         g_parsefile->next_to_pgetc = s;
10366         g_parsefile->left_in_line = len;
10367         g_parsefile->unget = 0;
10368         INT_ON;
10369 }
10370
10371 static void
10372 popstring(void)
10373 {
10374         struct strpush *sp = g_parsefile->strpush;
10375
10376         INT_OFF;
10377 #if ENABLE_ASH_ALIAS
10378         if (sp->ap) {
10379                 if (g_parsefile->next_to_pgetc[-1] == ' '
10380                  || g_parsefile->next_to_pgetc[-1] == '\t'
10381                 ) {
10382                         checkkwd |= CHKALIAS;
10383                 }
10384                 if (sp->string != sp->ap->val) {
10385                         free(sp->string);
10386                 }
10387                 sp->ap->flag &= ~ALIASINUSE;
10388                 if (sp->ap->flag & ALIASDEAD) {
10389                         unalias(sp->ap->name);
10390                 }
10391         }
10392 #endif
10393         g_parsefile->next_to_pgetc = sp->prev_string;
10394         g_parsefile->left_in_line = sp->prev_left_in_line;
10395         g_parsefile->unget = sp->unget;
10396         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10397         g_parsefile->strpush = sp->prev;
10398         if (sp != &(g_parsefile->basestrpush))
10399                 free(sp);
10400         INT_ON;
10401 }
10402
10403 static int
10404 preadfd(void)
10405 {
10406         int nr;
10407         char *buf = g_parsefile->buf;
10408
10409         g_parsefile->next_to_pgetc = buf;
10410 #if ENABLE_FEATURE_EDITING
10411  retry:
10412         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10413                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10414         else {
10415 # if ENABLE_ASH_IDLE_TIMEOUT
10416                 int timeout = -1;
10417                 if (iflag) {
10418                         const char *tmout_var = lookupvar("TMOUT");
10419                         if (tmout_var) {
10420                                 timeout = atoi(tmout_var) * 1000;
10421                                 if (timeout <= 0)
10422                                         timeout = -1;
10423                         }
10424                 }
10425                 line_input_state->timeout = timeout;
10426 # endif
10427 # if ENABLE_FEATURE_TAB_COMPLETION
10428                 line_input_state->path_lookup = pathval();
10429 # endif
10430                 reinit_unicode_for_ash();
10431                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10432                 if (nr == 0) {
10433                         /* ^C pressed, "convert" to SIGINT */
10434                         write(STDOUT_FILENO, "^C", 2);
10435                         if (trap[SIGINT]) {
10436                                 buf[0] = '\n';
10437                                 buf[1] = '\0';
10438                                 raise(SIGINT);
10439                                 return 1;
10440                         }
10441                         exitstatus = 128 + SIGINT;
10442                         bb_putchar('\n');
10443                         goto retry;
10444                 }
10445                 if (nr < 0) {
10446                         if (errno == 0) {
10447                                 /* Ctrl+D pressed */
10448                                 nr = 0;
10449                         }
10450 # if ENABLE_ASH_IDLE_TIMEOUT
10451                         else if (errno == EAGAIN && timeout > 0) {
10452                                 puts("\007timed out waiting for input: auto-logout");
10453                                 exitshell();
10454                         }
10455 # endif
10456                 }
10457         }
10458 #else
10459         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10460 #endif
10461
10462 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10463         if (nr < 0) {
10464                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10465                         int flags = fcntl(0, F_GETFL);
10466                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10467                                 flags &= ~O_NONBLOCK;
10468                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10469                                         out2str("sh: turning off NDELAY mode\n");
10470                                         goto retry;
10471                                 }
10472                         }
10473                 }
10474         }
10475 #endif
10476         return nr;
10477 }
10478
10479 /*
10480  * Refill the input buffer and return the next input character:
10481  *
10482  * 1) If a string was pushed back on the input, pop it;
10483  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10484  *    or we are reading from a string so we can't refill the buffer,
10485  *    return EOF.
10486  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10487  * 4) Process input up to the next newline, deleting nul characters.
10488  */
10489 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10490 #define pgetc_debug(...) ((void)0)
10491 static int pgetc(void);
10492 static int
10493 preadbuffer(void)
10494 {
10495         char *q;
10496         int more;
10497
10498         if (g_parsefile->strpush) {
10499 #if ENABLE_ASH_ALIAS
10500                 if (g_parsefile->left_in_line == -1
10501                  && g_parsefile->strpush->ap
10502                  && g_parsefile->next_to_pgetc[-1] != ' '
10503                  && g_parsefile->next_to_pgetc[-1] != '\t'
10504                 ) {
10505                         pgetc_debug("preadbuffer PEOA");
10506                         return PEOA;
10507                 }
10508 #endif
10509                 popstring();
10510                 return pgetc();
10511         }
10512         /* on both branches above g_parsefile->left_in_line < 0.
10513          * "pgetc" needs refilling.
10514          */
10515
10516         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10517          * pungetc() may increment it a few times.
10518          * Assuming it won't increment it to less than -90.
10519          */
10520         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10521                 pgetc_debug("preadbuffer PEOF1");
10522                 /* even in failure keep left_in_line and next_to_pgetc
10523                  * in lock step, for correct multi-layer pungetc.
10524                  * left_in_line was decremented before preadbuffer(),
10525                  * must inc next_to_pgetc: */
10526                 g_parsefile->next_to_pgetc++;
10527                 return PEOF;
10528         }
10529
10530         more = g_parsefile->left_in_buffer;
10531         if (more <= 0) {
10532                 flush_stdout_stderr();
10533  again:
10534                 more = preadfd();
10535                 if (more <= 0) {
10536                         /* don't try reading again */
10537                         g_parsefile->left_in_line = -99;
10538                         pgetc_debug("preadbuffer PEOF2");
10539                         g_parsefile->next_to_pgetc++;
10540                         return PEOF;
10541                 }
10542         }
10543
10544         /* Find out where's the end of line.
10545          * Set g_parsefile->left_in_line
10546          * and g_parsefile->left_in_buffer acordingly.
10547          * NUL chars are deleted.
10548          */
10549         q = g_parsefile->next_to_pgetc;
10550         for (;;) {
10551                 char c;
10552
10553                 more--;
10554
10555                 c = *q;
10556                 if (c == '\0') {
10557                         memmove(q, q + 1, more);
10558                 } else {
10559                         q++;
10560                         if (c == '\n') {
10561                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10562                                 break;
10563                         }
10564                 }
10565
10566                 if (more <= 0) {
10567                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10568                         if (g_parsefile->left_in_line < 0)
10569                                 goto again;
10570                         break;
10571                 }
10572         }
10573         g_parsefile->left_in_buffer = more;
10574
10575         if (vflag) {
10576                 char save = *q;
10577                 *q = '\0';
10578                 out2str(g_parsefile->next_to_pgetc);
10579                 *q = save;
10580         }
10581
10582         pgetc_debug("preadbuffer at %d:%p'%s'",
10583                         g_parsefile->left_in_line,
10584                         g_parsefile->next_to_pgetc,
10585                         g_parsefile->next_to_pgetc);
10586         return (unsigned char)*g_parsefile->next_to_pgetc++;
10587 }
10588
10589 static void
10590 nlprompt(void)
10591 {
10592         g_parsefile->linno++;
10593         setprompt_if(doprompt, 2);
10594 }
10595 static void
10596 nlnoprompt(void)
10597 {
10598         g_parsefile->linno++;
10599         needprompt = doprompt;
10600 }
10601
10602 static int
10603 pgetc(void)
10604 {
10605         int c;
10606
10607         pgetc_debug("pgetc at %d:%p'%s'",
10608                         g_parsefile->left_in_line,
10609                         g_parsefile->next_to_pgetc,
10610                         g_parsefile->next_to_pgetc);
10611         if (g_parsefile->unget)
10612                 return g_parsefile->lastc[--g_parsefile->unget];
10613
10614         if (--g_parsefile->left_in_line >= 0)
10615                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10616         else
10617                 c = preadbuffer();
10618
10619         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10620         g_parsefile->lastc[0] = c;
10621
10622         return c;
10623 }
10624
10625 #if ENABLE_ASH_ALIAS
10626 static int
10627 pgetc_without_PEOA(void)
10628 {
10629         int c;
10630         do {
10631                 pgetc_debug("pgetc at %d:%p'%s'",
10632                                 g_parsefile->left_in_line,
10633                                 g_parsefile->next_to_pgetc,
10634                                 g_parsefile->next_to_pgetc);
10635                 c = pgetc();
10636         } while (c == PEOA);
10637         return c;
10638 }
10639 #else
10640 # define pgetc_without_PEOA() pgetc()
10641 #endif
10642
10643 /*
10644  * Undo a call to pgetc.  Only two characters may be pushed back.
10645  * PEOF may be pushed back.
10646  */
10647 static void
10648 pungetc(void)
10649 {
10650         g_parsefile->unget++;
10651 }
10652
10653 /* This one eats backslash+newline */
10654 static int
10655 pgetc_eatbnl(void)
10656 {
10657         int c;
10658
10659         while ((c = pgetc()) == '\\') {
10660                 if (pgetc() != '\n') {
10661                         pungetc();
10662                         break;
10663                 }
10664
10665                 nlprompt();
10666         }
10667
10668         return c;
10669 }
10670
10671 struct synstack {
10672         smalluint syntax;
10673         uint8_t innerdq   :1;
10674         uint8_t varpushed :1;
10675         uint8_t dblquote  :1;
10676         int varnest;            /* levels of variables expansion */
10677         int dqvarnest;          /* levels of variables expansion within double quotes */
10678         int parenlevel;         /* levels of parens in arithmetic */
10679         struct synstack *prev;
10680         struct synstack *next;
10681 };
10682
10683 static void
10684 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10685 {
10686         memset(next, 0, sizeof(*next));
10687         next->syntax = syntax;
10688         next->next = *stack;
10689         (*stack)->prev = next;
10690         *stack = next;
10691 }
10692
10693 static ALWAYS_INLINE void
10694 synstack_pop(struct synstack **stack)
10695 {
10696         *stack = (*stack)->next;
10697 }
10698
10699 /*
10700  * To handle the "." command, a stack of input files is used.  Pushfile
10701  * adds a new entry to the stack and popfile restores the previous level.
10702  */
10703 static void
10704 pushfile(void)
10705 {
10706         struct parsefile *pf;
10707
10708         pf = ckzalloc(sizeof(*pf));
10709         pf->prev = g_parsefile;
10710         pf->pf_fd = -1;
10711         /*pf->strpush = NULL; - ckzalloc did it */
10712         /*pf->basestrpush.prev = NULL;*/
10713         /*pf->unget = 0;*/
10714         g_parsefile = pf;
10715 }
10716
10717 static void
10718 popfile(void)
10719 {
10720         struct parsefile *pf = g_parsefile;
10721
10722         if (pf == &basepf)
10723                 return;
10724
10725         INT_OFF;
10726         if (pf->pf_fd >= 0)
10727                 close(pf->pf_fd);
10728         free(pf->buf);
10729         while (pf->strpush)
10730                 popstring();
10731         g_parsefile = pf->prev;
10732         free(pf);
10733         INT_ON;
10734 }
10735
10736 /*
10737  * Return to top level.
10738  */
10739 static void
10740 popallfiles(void)
10741 {
10742         while (g_parsefile != &basepf)
10743                 popfile();
10744 }
10745
10746 /*
10747  * Close the file(s) that the shell is reading commands from.  Called
10748  * after a fork is done.
10749  */
10750 static void
10751 closescript(void)
10752 {
10753         popallfiles();
10754         if (g_parsefile->pf_fd > 0) {
10755                 close(g_parsefile->pf_fd);
10756                 g_parsefile->pf_fd = 0;
10757         }
10758 }
10759
10760 /*
10761  * Like setinputfile, but takes an open file descriptor.  Call this with
10762  * interrupts off.
10763  */
10764 static void
10765 setinputfd(int fd, int push)
10766 {
10767         if (push) {
10768                 pushfile();
10769                 g_parsefile->buf = NULL;
10770         }
10771         g_parsefile->pf_fd = fd;
10772         if (g_parsefile->buf == NULL)
10773                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10774         g_parsefile->left_in_buffer = 0;
10775         g_parsefile->left_in_line = 0;
10776         g_parsefile->linno = 1;
10777 }
10778
10779 /*
10780  * Set the input to take input from a file.  If push is set, push the
10781  * old input onto the stack first.
10782  */
10783 static int
10784 setinputfile(const char *fname, int flags)
10785 {
10786         int fd;
10787
10788         INT_OFF;
10789         fd = open(fname, O_RDONLY | O_CLOEXEC);
10790         if (fd < 0) {
10791                 if (flags & INPUT_NOFILE_OK)
10792                         goto out;
10793                 exitstatus = 127;
10794                 ash_msg_and_raise_perror("can't open '%s'", fname);
10795         }
10796         if (fd < 10)
10797                 fd = savefd(fd);
10798         else if (O_CLOEXEC == 0) /* old libc */
10799                 close_on_exec_on(fd);
10800
10801         setinputfd(fd, flags & INPUT_PUSH_FILE);
10802  out:
10803         INT_ON;
10804         return fd;
10805 }
10806
10807 /*
10808  * Like setinputfile, but takes input from a string.
10809  */
10810 static void
10811 setinputstring(char *string)
10812 {
10813         INT_OFF;
10814         pushfile();
10815         g_parsefile->next_to_pgetc = string;
10816         g_parsefile->left_in_line = strlen(string);
10817         g_parsefile->buf = NULL;
10818         g_parsefile->linno = 1;
10819         INT_ON;
10820 }
10821
10822
10823 /*
10824  * Routines to check for mail.
10825  */
10826
10827 #if ENABLE_ASH_MAIL
10828
10829 /* Hash of mtimes of mailboxes */
10830 static unsigned mailtime_hash;
10831 /* Set if MAIL or MAILPATH is changed. */
10832 static smallint mail_var_path_changed;
10833
10834 /*
10835  * Print appropriate message(s) if mail has arrived.
10836  * If mail_var_path_changed is set,
10837  * then the value of MAIL has mail_var_path_changed,
10838  * so we just update the values.
10839  */
10840 static void
10841 chkmail(void)
10842 {
10843         const char *mpath;
10844         char *p;
10845         char *q;
10846         unsigned new_hash;
10847         struct stackmark smark;
10848         struct stat statb;
10849
10850         setstackmark(&smark);
10851         mpath = mpathset() ? mpathval() : mailval();
10852         new_hash = 0;
10853         for (;;) {
10854                 p = path_advance(&mpath, nullstr);
10855                 if (p == NULL)
10856                         break;
10857                 if (*p == '\0')
10858                         continue;
10859                 for (q = p; *q; q++)
10860                         continue;
10861 #if DEBUG
10862                 if (q[-1] != '/')
10863                         abort();
10864 #endif
10865                 q[-1] = '\0';                   /* delete trailing '/' */
10866                 if (stat(p, &statb) < 0) {
10867                         continue;
10868                 }
10869                 /* Very simplistic "hash": just a sum of all mtimes */
10870                 new_hash += (unsigned)statb.st_mtime;
10871         }
10872         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10873                 if (mailtime_hash != 0)
10874                         out2str("you have mail\n");
10875                 mailtime_hash = new_hash;
10876         }
10877         mail_var_path_changed = 0;
10878         popstackmark(&smark);
10879 }
10880
10881 static void FAST_FUNC
10882 changemail(const char *val UNUSED_PARAM)
10883 {
10884         mail_var_path_changed = 1;
10885 }
10886
10887 #endif /* ASH_MAIL */
10888
10889
10890 /* ============ ??? */
10891
10892 /*
10893  * Set the shell parameters.
10894  */
10895 static void
10896 setparam(char **argv)
10897 {
10898         char **newparam;
10899         char **ap;
10900         int nparam;
10901
10902         for (nparam = 0; argv[nparam]; nparam++)
10903                 continue;
10904         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10905         while (*argv) {
10906                 *ap++ = ckstrdup(*argv++);
10907         }
10908         *ap = NULL;
10909         freeparam(&shellparam);
10910         shellparam.malloced = 1;
10911         shellparam.nparam = nparam;
10912         shellparam.p = newparam;
10913 #if ENABLE_ASH_GETOPTS
10914         shellparam.optind = 1;
10915         shellparam.optoff = -1;
10916 #endif
10917 }
10918
10919 /*
10920  * Process shell options.  The global variable argptr contains a pointer
10921  * to the argument list; we advance it past the options.
10922  *
10923  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10924  * For a non-interactive shell, an error condition encountered
10925  * by a special built-in ... shall cause the shell to write a diagnostic message
10926  * to standard error and exit as shown in the following table:
10927  * Error                                           Special Built-In
10928  * ...
10929  * Utility syntax error (option or operand error)  Shall exit
10930  * ...
10931  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10932  * we see that bash does not do that (set "finishes" with error code 1 instead,
10933  * and shell continues), and people rely on this behavior!
10934  * Testcase:
10935  * set -o barfoo 2>/dev/null
10936  * echo $?
10937  *
10938  * Oh well. Let's mimic that.
10939  */
10940 static int
10941 plus_minus_o(char *name, int val)
10942 {
10943         int i;
10944
10945         if (name) {
10946                 for (i = 0; i < NOPTS; i++) {
10947                         if (strcmp(name, optnames(i)) == 0) {
10948                                 optlist[i] = val;
10949                                 return 0;
10950                         }
10951                 }
10952                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10953                 return 1;
10954         }
10955         for (i = 0; i < NOPTS; i++) {
10956                 if (val) {
10957                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10958                 } else {
10959                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10960                 }
10961         }
10962         return 0;
10963 }
10964 static void
10965 setoption(int flag, int val)
10966 {
10967         int i;
10968
10969         for (i = 0; i < NOPTS; i++) {
10970                 if (optletters(i) == flag) {
10971                         optlist[i] = val;
10972                         return;
10973                 }
10974         }
10975         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10976         /* NOTREACHED */
10977 }
10978 static int
10979 options(int cmdline, int *login_sh)
10980 {
10981         char *p;
10982         int val;
10983         int c;
10984
10985         if (cmdline)
10986                 minusc = NULL;
10987         while ((p = *argptr) != NULL) {
10988                 c = *p++;
10989                 if (c != '-' && c != '+')
10990                         break;
10991                 argptr++;
10992                 val = 0; /* val = 0 if c == '+' */
10993                 if (c == '-') {
10994                         val = 1;
10995                         if (p[0] == '\0' || LONE_DASH(p)) {
10996                                 if (!cmdline) {
10997                                         /* "-" means turn off -x and -v */
10998                                         if (p[0] == '\0')
10999                                                 xflag = vflag = 0;
11000                                         /* "--" means reset params */
11001                                         else if (*argptr == NULL)
11002                                                 setparam(argptr);
11003                                 }
11004                                 break;    /* "-" or "--" terminates options */
11005                         }
11006                 }
11007                 /* first char was + or - */
11008                 while ((c = *p++) != '\0') {
11009                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11010                         if (c == 'c' && cmdline) {
11011                                 minusc = p;     /* command is after shell args */
11012                         } else if (c == 'o') {
11013                                 if (plus_minus_o(*argptr, val)) {
11014                                         /* it already printed err message */
11015                                         return 1; /* error */
11016                                 }
11017                                 if (*argptr)
11018                                         argptr++;
11019                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11020                                 if (login_sh)
11021                                         *login_sh = 1;
11022                         /* bash does not accept +-login, we also won't */
11023                         } else if (cmdline && val && (c == '-')) { /* long options */
11024                                 if (strcmp(p, "login") == 0) {
11025                                         if (login_sh)
11026                                                 *login_sh = 1;
11027                                 }
11028                                 break;
11029                         } else {
11030                                 setoption(c, val);
11031                         }
11032                 }
11033         }
11034         return 0;
11035 }
11036
11037 /*
11038  * The shift builtin command.
11039  */
11040 static int FAST_FUNC
11041 shiftcmd(int argc UNUSED_PARAM, char **argv)
11042 {
11043         int n;
11044         char **ap1, **ap2;
11045
11046         n = 1;
11047         if (argv[1])
11048                 n = number(argv[1]);
11049         if (n > shellparam.nparam)
11050                 return 1;
11051         INT_OFF;
11052         shellparam.nparam -= n;
11053         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11054                 if (shellparam.malloced)
11055                         free(*ap1);
11056         }
11057         ap2 = shellparam.p;
11058         while ((*ap2++ = *ap1++) != NULL)
11059                 continue;
11060 #if ENABLE_ASH_GETOPTS
11061         shellparam.optind = 1;
11062         shellparam.optoff = -1;
11063 #endif
11064         INT_ON;
11065         return 0;
11066 }
11067
11068 /*
11069  * POSIX requires that 'set' (but not export or readonly) output the
11070  * variables in lexicographic order - by the locale's collating order (sigh).
11071  * Maybe we could keep them in an ordered balanced binary tree
11072  * instead of hashed lists.
11073  * For now just roll 'em through qsort for printing...
11074  */
11075 static int
11076 showvars(const char *sep_prefix, int on, int off)
11077 {
11078         const char *sep;
11079         char **ep, **epend;
11080
11081         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11082         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11083
11084         sep = *sep_prefix ? " " : sep_prefix;
11085
11086         for (; ep < epend; ep++) {
11087                 const char *p;
11088                 const char *q;
11089
11090                 p = endofname(*ep);
11091 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11092  * makes "export -p" to have output not suitable for "eval":
11093  * import os
11094  * os.environ["test-test"]="test"
11095  * if os.fork() == 0:
11096  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11097  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11098  */
11099                 q = nullstr;
11100                 if (*p == '=')
11101                         q = single_quote(++p);
11102                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11103         }
11104         return 0;
11105 }
11106
11107 /*
11108  * The set command builtin.
11109  */
11110 static int FAST_FUNC
11111 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11112 {
11113         int retval;
11114
11115         if (!argv[1])
11116                 return showvars(nullstr, 0, VUNSET);
11117
11118         INT_OFF;
11119         retval = options(/*cmdline:*/ 0, NULL);
11120         if (retval == 0) { /* if no parse error... */
11121                 optschanged();
11122                 if (*argptr != NULL) {
11123                         setparam(argptr);
11124                 }
11125         }
11126         INT_ON;
11127         return retval;
11128 }
11129
11130 #if ENABLE_ASH_RANDOM_SUPPORT
11131 static void FAST_FUNC
11132 change_random(const char *value)
11133 {
11134         uint32_t t;
11135
11136         if (value == NULL) {
11137                 /* "get", generate */
11138                 t = next_random(&random_gen);
11139                 /* set without recursion */
11140                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11141                 vrandom.flags &= ~VNOFUNC;
11142         } else {
11143                 /* set/reset */
11144                 t = strtoul(value, NULL, 10);
11145                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11146         }
11147 }
11148 #endif
11149
11150 #if ENABLE_ASH_GETOPTS
11151 static int
11152 getopts(char *optstr, char *optvar, char **optfirst)
11153 {
11154         char *p, *q;
11155         char c = '?';
11156         int done = 0;
11157         char sbuf[2];
11158         char **optnext;
11159         int ind = shellparam.optind;
11160         int off = shellparam.optoff;
11161
11162         sbuf[1] = '\0';
11163
11164         shellparam.optind = -1;
11165         optnext = optfirst + ind - 1;
11166
11167         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11168                 p = NULL;
11169         else
11170                 p = optnext[-1] + off;
11171         if (p == NULL || *p == '\0') {
11172                 /* Current word is done, advance */
11173                 p = *optnext;
11174                 if (p == NULL || *p != '-' || *++p == '\0') {
11175  atend:
11176                         unsetvar("OPTARG");
11177                         p = NULL;
11178                         done = 1;
11179                         goto out;
11180                 }
11181                 optnext++;
11182                 if (LONE_DASH(p))        /* check for "--" */
11183                         goto atend;
11184         }
11185
11186         c = *p++;
11187         for (q = optstr; *q != c;) {
11188                 if (*q == '\0') {
11189                         /* OPTERR is a bashism */
11190                         const char *cp = lookupvar("OPTERR");
11191                         if ((cp && LONE_CHAR(cp, '0'))
11192                          || (optstr[0] == ':')
11193                         ) {
11194                                 sbuf[0] = c;
11195                                 /*sbuf[1] = '\0'; - already is */
11196                                 setvar0("OPTARG", sbuf);
11197                         } else {
11198                                 fprintf(stderr, "Illegal option -%c\n", c);
11199                                 unsetvar("OPTARG");
11200                         }
11201                         c = '?';
11202                         goto out;
11203                 }
11204                 if (*++q == ':')
11205                         q++;
11206         }
11207
11208         if (*++q == ':') {
11209                 if (*p == '\0' && (p = *optnext) == NULL) {
11210                         /* OPTERR is a bashism */
11211                         const char *cp = lookupvar("OPTERR");
11212                         if ((cp && LONE_CHAR(cp, '0'))
11213                          || (optstr[0] == ':')
11214                         ) {
11215                                 sbuf[0] = c;
11216                                 /*sbuf[1] = '\0'; - already is */
11217                                 setvar0("OPTARG", sbuf);
11218                                 c = ':';
11219                         } else {
11220                                 fprintf(stderr, "No arg for -%c option\n", c);
11221                                 unsetvar("OPTARG");
11222                                 c = '?';
11223                         }
11224                         goto out;
11225                 }
11226
11227                 if (p == *optnext)
11228                         optnext++;
11229                 setvar0("OPTARG", p);
11230                 p = NULL;
11231         } else
11232                 setvar0("OPTARG", nullstr);
11233  out:
11234         ind = optnext - optfirst + 1;
11235         setvar("OPTIND", itoa(ind), VNOFUNC);
11236         sbuf[0] = c;
11237         /*sbuf[1] = '\0'; - already is */
11238         setvar0(optvar, sbuf);
11239
11240         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11241         shellparam.optind = ind;
11242
11243         return done;
11244 }
11245
11246 /*
11247  * The getopts builtin.  Shellparam.optnext points to the next argument
11248  * to be processed.  Shellparam.optptr points to the next character to
11249  * be processed in the current argument.  If shellparam.optnext is NULL,
11250  * then it's the first time getopts has been called.
11251  */
11252 static int FAST_FUNC
11253 getoptscmd(int argc, char **argv)
11254 {
11255         char **optbase;
11256
11257         if (argc < 3)
11258                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11259         if (argc == 3) {
11260                 optbase = shellparam.p;
11261                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11262                         shellparam.optind = 1;
11263                         shellparam.optoff = -1;
11264                 }
11265         } else {
11266                 optbase = &argv[3];
11267                 if ((unsigned)shellparam.optind > argc - 2) {
11268                         shellparam.optind = 1;
11269                         shellparam.optoff = -1;
11270                 }
11271         }
11272
11273         return getopts(argv[1], argv[2], optbase);
11274 }
11275 #endif /* ASH_GETOPTS */
11276
11277
11278 /* ============ Shell parser */
11279
11280 struct heredoc {
11281         struct heredoc *next;   /* next here document in list */
11282         union node *here;       /* redirection node */
11283         char *eofmark;          /* string indicating end of input */
11284         smallint striptabs;     /* if set, strip leading tabs */
11285 };
11286
11287 static smallint tokpushback;           /* last token pushed back */
11288 static smallint quoteflag;             /* set if (part of) last token was quoted */
11289 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11290 static struct heredoc *heredoclist;    /* list of here documents to read */
11291 static char *wordtext;                 /* text of last word returned by readtoken */
11292 static struct nodelist *backquotelist;
11293 static union node *redirnode;
11294 static struct heredoc *heredoc;
11295
11296 static const char *
11297 tokname(char *buf, int tok)
11298 {
11299         if (tok < TSEMI)
11300                 return tokname_array[tok];
11301         sprintf(buf, "\"%s\"", tokname_array[tok]);
11302         return buf;
11303 }
11304
11305 /* raise_error_unexpected_syntax:
11306  * Called when an unexpected token is read during the parse.  The argument
11307  * is the token that is expected, or -1 if more than one type of token can
11308  * occur at this point.
11309  */
11310 static void raise_error_unexpected_syntax(int) NORETURN;
11311 static void
11312 raise_error_unexpected_syntax(int token)
11313 {
11314         char msg[64];
11315         char buf[16];
11316         int l;
11317
11318         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11319         if (token >= 0)
11320                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11321         raise_error_syntax(msg);
11322         /* NOTREACHED */
11323 }
11324
11325 /* parsing is heavily cross-recursive, need these forward decls */
11326 static union node *andor(void);
11327 static union node *pipeline(void);
11328 static union node *parse_command(void);
11329 static void parseheredoc(void);
11330 static int peektoken(void);
11331 static int readtoken(void);
11332
11333 static union node *
11334 list(int nlflag)
11335 {
11336         union node *n1, *n2, *n3;
11337         int tok;
11338
11339         n1 = NULL;
11340         for (;;) {
11341                 switch (peektoken()) {
11342                 case TNL:
11343                         if (!(nlflag & 1))
11344                                 break;
11345                         parseheredoc();
11346                         return n1;
11347
11348                 case TEOF:
11349                         if (!n1 && (nlflag & 1))
11350                                 n1 = NODE_EOF;
11351                         parseheredoc();
11352                         return n1;
11353                 }
11354
11355                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11356                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11357                         return n1;
11358                 nlflag |= 2;
11359
11360                 n2 = andor();
11361                 tok = readtoken();
11362                 if (tok == TBACKGND) {
11363                         if (n2->type == NPIPE) {
11364                                 n2->npipe.pipe_backgnd = 1;
11365                         } else {
11366                                 if (n2->type != NREDIR) {
11367                                         n3 = stzalloc(sizeof(struct nredir));
11368                                         n3->nredir.n = n2;
11369                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11370                                         n2 = n3;
11371                                 }
11372                                 n2->type = NBACKGND;
11373                         }
11374                 }
11375                 if (n1 == NULL) {
11376                         n1 = n2;
11377                 } else {
11378                         n3 = stzalloc(sizeof(struct nbinary));
11379                         n3->type = NSEMI;
11380                         n3->nbinary.ch1 = n1;
11381                         n3->nbinary.ch2 = n2;
11382                         n1 = n3;
11383                 }
11384                 switch (tok) {
11385                 case TNL:
11386                 case TEOF:
11387                         tokpushback = 1;
11388                         /* fall through */
11389                 case TBACKGND:
11390                 case TSEMI:
11391                         break;
11392                 default:
11393                         if ((nlflag & 1))
11394                                 raise_error_unexpected_syntax(-1);
11395                         tokpushback = 1;
11396                         return n1;
11397                 }
11398         }
11399 }
11400
11401 static union node *
11402 andor(void)
11403 {
11404         union node *n1, *n2, *n3;
11405         int t;
11406
11407         n1 = pipeline();
11408         for (;;) {
11409                 t = readtoken();
11410                 if (t == TAND) {
11411                         t = NAND;
11412                 } else if (t == TOR) {
11413                         t = NOR;
11414                 } else {
11415                         tokpushback = 1;
11416                         return n1;
11417                 }
11418                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11419                 n2 = pipeline();
11420                 n3 = stzalloc(sizeof(struct nbinary));
11421                 n3->type = t;
11422                 n3->nbinary.ch1 = n1;
11423                 n3->nbinary.ch2 = n2;
11424                 n1 = n3;
11425         }
11426 }
11427
11428 static union node *
11429 pipeline(void)
11430 {
11431         union node *n1, *n2, *pipenode;
11432         struct nodelist *lp, *prev;
11433         int negate;
11434
11435         negate = 0;
11436         TRACE(("pipeline: entered\n"));
11437         if (readtoken() == TNOT) {
11438                 negate = !negate;
11439                 checkkwd = CHKKWD | CHKALIAS;
11440         } else
11441                 tokpushback = 1;
11442         n1 = parse_command();
11443         if (readtoken() == TPIPE) {
11444                 pipenode = stzalloc(sizeof(struct npipe));
11445                 pipenode->type = NPIPE;
11446                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11447                 lp = stzalloc(sizeof(struct nodelist));
11448                 pipenode->npipe.cmdlist = lp;
11449                 lp->n = n1;
11450                 do {
11451                         prev = lp;
11452                         lp = stzalloc(sizeof(struct nodelist));
11453                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11454                         lp->n = parse_command();
11455                         prev->next = lp;
11456                 } while (readtoken() == TPIPE);
11457                 lp->next = NULL;
11458                 n1 = pipenode;
11459         }
11460         tokpushback = 1;
11461         if (negate) {
11462                 n2 = stzalloc(sizeof(struct nnot));
11463                 n2->type = NNOT;
11464                 n2->nnot.com = n1;
11465                 return n2;
11466         }
11467         return n1;
11468 }
11469
11470 static union node *
11471 makename(void)
11472 {
11473         union node *n;
11474
11475         n = stzalloc(sizeof(struct narg));
11476         n->type = NARG;
11477         /*n->narg.next = NULL; - stzalloc did it */
11478         n->narg.text = wordtext;
11479         n->narg.backquote = backquotelist;
11480         return n;
11481 }
11482
11483 static void
11484 fixredir(union node *n, const char *text, int err)
11485 {
11486         int fd;
11487
11488         TRACE(("Fix redir %s %d\n", text, err));
11489         if (!err)
11490                 n->ndup.vname = NULL;
11491
11492         fd = bb_strtou(text, NULL, 10);
11493         if (!errno && fd >= 0)
11494                 n->ndup.dupfd = fd;
11495         else if (LONE_DASH(text))
11496                 n->ndup.dupfd = -1;
11497         else {
11498                 if (err)
11499                         raise_error_syntax("bad fd number");
11500                 n->ndup.vname = makename();
11501         }
11502 }
11503
11504 static void
11505 parsefname(void)
11506 {
11507         union node *n = redirnode;
11508
11509         if (n->type == NHERE)
11510                 checkkwd = CHKEOFMARK;
11511         if (readtoken() != TWORD)
11512                 raise_error_unexpected_syntax(-1);
11513         if (n->type == NHERE) {
11514                 struct heredoc *here = heredoc;
11515                 struct heredoc *p;
11516
11517                 if (quoteflag == 0)
11518                         n->type = NXHERE;
11519                 TRACE(("Here document %d\n", n->type));
11520                 rmescapes(wordtext, 0, NULL);
11521                 here->eofmark = wordtext;
11522                 here->next = NULL;
11523                 if (heredoclist == NULL)
11524                         heredoclist = here;
11525                 else {
11526                         for (p = heredoclist; p->next; p = p->next)
11527                                 continue;
11528                         p->next = here;
11529                 }
11530         } else if (n->type == NTOFD || n->type == NFROMFD) {
11531                 fixredir(n, wordtext, 0);
11532         } else {
11533                 n->nfile.fname = makename();
11534         }
11535 }
11536
11537 static union node *
11538 simplecmd(void)
11539 {
11540         union node *args, **app;
11541         union node *n = NULL;
11542         union node *vars, **vpp;
11543         union node **rpp, *redir;
11544         int savecheckkwd;
11545         int savelinno;
11546 #if BASH_TEST2
11547         smallint double_brackets_flag = 0;
11548 #endif
11549         IF_BASH_FUNCTION(smallint function_flag = 0;)
11550
11551         args = NULL;
11552         app = &args;
11553         vars = NULL;
11554         vpp = &vars;
11555         redir = NULL;
11556         rpp = &redir;
11557
11558         savecheckkwd = CHKALIAS;
11559         savelinno = g_parsefile->linno;
11560         for (;;) {
11561                 int t;
11562                 checkkwd = savecheckkwd;
11563                 t = readtoken();
11564                 switch (t) {
11565 #if BASH_FUNCTION
11566                 case TFUNCTION:
11567                         if (peektoken() != TWORD)
11568                                 raise_error_unexpected_syntax(TWORD);
11569                         function_flag = 1;
11570                         break;
11571 #endif
11572 #if BASH_TEST2
11573                 case TAND: /* "&&" */
11574                 case TOR: /* "||" */
11575                         if (!double_brackets_flag) {
11576                                 tokpushback = 1;
11577                                 goto out;
11578                         }
11579                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11580 #endif
11581                 case TWORD:
11582                         n = stzalloc(sizeof(struct narg));
11583                         n->type = NARG;
11584                         /*n->narg.next = NULL; - stzalloc did it */
11585                         n->narg.text = wordtext;
11586 #if BASH_TEST2
11587                         if (strcmp("[[", wordtext) == 0)
11588                                 double_brackets_flag = 1;
11589                         else if (strcmp("]]", wordtext) == 0)
11590                                 double_brackets_flag = 0;
11591 #endif
11592                         n->narg.backquote = backquotelist;
11593                         if (savecheckkwd && isassignment(wordtext)) {
11594                                 *vpp = n;
11595                                 vpp = &n->narg.next;
11596                         } else {
11597                                 *app = n;
11598                                 app = &n->narg.next;
11599                                 savecheckkwd = 0;
11600                         }
11601 #if BASH_FUNCTION
11602                         if (function_flag) {
11603                                 checkkwd = CHKNL | CHKKWD;
11604                                 switch (peektoken()) {
11605                                 case TBEGIN:
11606                                 case TIF:
11607                                 case TCASE:
11608                                 case TUNTIL:
11609                                 case TWHILE:
11610                                 case TFOR:
11611                                         goto do_func;
11612                                 case TLP:
11613                                         function_flag = 0;
11614                                         break;
11615                                 case TWORD:
11616                                         if (strcmp("[[", wordtext) == 0)
11617                                                 goto do_func;
11618                                         /* fall through */
11619                                 default:
11620                                         raise_error_unexpected_syntax(-1);
11621                                 }
11622                         }
11623 #endif
11624                         break;
11625                 case TREDIR:
11626                         *rpp = n = redirnode;
11627                         rpp = &n->nfile.next;
11628                         parsefname();   /* read name of redirection file */
11629                         break;
11630                 case TLP:
11631  IF_BASH_FUNCTION(do_func:)
11632                         if (args && app == &args->narg.next
11633                          && !vars && !redir
11634                         ) {
11635                                 struct builtincmd *bcmd;
11636                                 const char *name;
11637
11638                                 /* We have a function */
11639                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11640                                         raise_error_unexpected_syntax(TRP);
11641                                 name = n->narg.text;
11642                                 if (!goodname(name)
11643                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11644                                 ) {
11645                                         raise_error_syntax("bad function name");
11646                                 }
11647                                 n->type = NDEFUN;
11648                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11649                                 n->ndefun.text = n->narg.text;
11650                                 n->ndefun.linno = g_parsefile->linno;
11651                                 n->ndefun.body = parse_command();
11652                                 return n;
11653                         }
11654                         IF_BASH_FUNCTION(function_flag = 0;)
11655                         /* fall through */
11656                 default:
11657                         tokpushback = 1;
11658                         goto out;
11659                 }
11660         }
11661  out:
11662         *app = NULL;
11663         *vpp = NULL;
11664         *rpp = NULL;
11665         n = stzalloc(sizeof(struct ncmd));
11666         n->type = NCMD;
11667         n->ncmd.linno = savelinno;
11668         n->ncmd.args = args;
11669         n->ncmd.assign = vars;
11670         n->ncmd.redirect = redir;
11671         return n;
11672 }
11673
11674 static union node *
11675 parse_command(void)
11676 {
11677         union node *n1, *n2;
11678         union node *ap, **app;
11679         union node *cp, **cpp;
11680         union node *redir, **rpp;
11681         union node **rpp2;
11682         int t;
11683         int savelinno;
11684
11685         redir = NULL;
11686         rpp2 = &redir;
11687
11688         savelinno = g_parsefile->linno;
11689
11690         switch (readtoken()) {
11691         default:
11692                 raise_error_unexpected_syntax(-1);
11693                 /* NOTREACHED */
11694         case TIF:
11695                 n1 = stzalloc(sizeof(struct nif));
11696                 n1->type = NIF;
11697                 n1->nif.test = list(0);
11698                 if (readtoken() != TTHEN)
11699                         raise_error_unexpected_syntax(TTHEN);
11700                 n1->nif.ifpart = list(0);
11701                 n2 = n1;
11702                 while (readtoken() == TELIF) {
11703                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11704                         n2 = n2->nif.elsepart;
11705                         n2->type = NIF;
11706                         n2->nif.test = list(0);
11707                         if (readtoken() != TTHEN)
11708                                 raise_error_unexpected_syntax(TTHEN);
11709                         n2->nif.ifpart = list(0);
11710                 }
11711                 if (lasttoken == TELSE)
11712                         n2->nif.elsepart = list(0);
11713                 else {
11714                         n2->nif.elsepart = NULL;
11715                         tokpushback = 1;
11716                 }
11717                 t = TFI;
11718                 break;
11719         case TWHILE:
11720         case TUNTIL: {
11721                 int got;
11722                 n1 = stzalloc(sizeof(struct nbinary));
11723                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11724                 n1->nbinary.ch1 = list(0);
11725                 got = readtoken();
11726                 if (got != TDO) {
11727                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11728                                         got == TWORD ? wordtext : ""));
11729                         raise_error_unexpected_syntax(TDO);
11730                 }
11731                 n1->nbinary.ch2 = list(0);
11732                 t = TDONE;
11733                 break;
11734         }
11735         case TFOR:
11736                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11737                         raise_error_syntax("bad for loop variable");
11738                 n1 = stzalloc(sizeof(struct nfor));
11739                 n1->type = NFOR;
11740                 n1->nfor.linno = savelinno;
11741                 n1->nfor.var = wordtext;
11742                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11743                 if (readtoken() == TIN) {
11744                         app = &ap;
11745                         while (readtoken() == TWORD) {
11746                                 n2 = stzalloc(sizeof(struct narg));
11747                                 n2->type = NARG;
11748                                 /*n2->narg.next = NULL; - stzalloc did it */
11749                                 n2->narg.text = wordtext;
11750                                 n2->narg.backquote = backquotelist;
11751                                 *app = n2;
11752                                 app = &n2->narg.next;
11753                         }
11754                         *app = NULL;
11755                         n1->nfor.args = ap;
11756                         if (lasttoken != TNL && lasttoken != TSEMI)
11757                                 raise_error_unexpected_syntax(-1);
11758                 } else {
11759                         n2 = stzalloc(sizeof(struct narg));
11760                         n2->type = NARG;
11761                         /*n2->narg.next = NULL; - stzalloc did it */
11762                         n2->narg.text = (char *)dolatstr;
11763                         /*n2->narg.backquote = NULL;*/
11764                         n1->nfor.args = n2;
11765                         /*
11766                          * Newline or semicolon here is optional (but note
11767                          * that the original Bourne shell only allowed NL).
11768                          */
11769                         if (lasttoken != TSEMI)
11770                                 tokpushback = 1;
11771                 }
11772                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11773                 if (readtoken() != TDO)
11774                         raise_error_unexpected_syntax(TDO);
11775                 n1->nfor.body = list(0);
11776                 t = TDONE;
11777                 break;
11778         case TCASE:
11779                 n1 = stzalloc(sizeof(struct ncase));
11780                 n1->type = NCASE;
11781                 n1->ncase.linno = savelinno;
11782                 if (readtoken() != TWORD)
11783                         raise_error_unexpected_syntax(TWORD);
11784                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11785                 n2->type = NARG;
11786                 /*n2->narg.next = NULL; - stzalloc did it */
11787                 n2->narg.text = wordtext;
11788                 n2->narg.backquote = backquotelist;
11789                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11790                 if (readtoken() != TIN)
11791                         raise_error_unexpected_syntax(TIN);
11792                 cpp = &n1->ncase.cases;
11793  next_case:
11794                 checkkwd = CHKNL | CHKKWD;
11795                 t = readtoken();
11796                 while (t != TESAC) {
11797                         if (lasttoken == TLP)
11798                                 readtoken();
11799                         *cpp = cp = stzalloc(sizeof(struct nclist));
11800                         cp->type = NCLIST;
11801                         app = &cp->nclist.pattern;
11802                         for (;;) {
11803                                 *app = ap = stzalloc(sizeof(struct narg));
11804                                 ap->type = NARG;
11805                                 /*ap->narg.next = NULL; - stzalloc did it */
11806                                 ap->narg.text = wordtext;
11807                                 ap->narg.backquote = backquotelist;
11808                                 if (readtoken() != TPIPE)
11809                                         break;
11810                                 app = &ap->narg.next;
11811                                 readtoken();
11812                         }
11813                         //ap->narg.next = NULL;
11814                         if (lasttoken != TRP)
11815                                 raise_error_unexpected_syntax(TRP);
11816                         cp->nclist.body = list(2);
11817
11818                         cpp = &cp->nclist.next;
11819
11820                         checkkwd = CHKNL | CHKKWD;
11821                         t = readtoken();
11822                         if (t != TESAC) {
11823                                 if (t != TENDCASE)
11824                                         raise_error_unexpected_syntax(TENDCASE);
11825                                 goto next_case;
11826                         }
11827                 }
11828                 *cpp = NULL;
11829                 goto redir;
11830         case TLP:
11831                 n1 = stzalloc(sizeof(struct nredir));
11832                 n1->type = NSUBSHELL;
11833                 n1->nredir.linno = savelinno;
11834                 n1->nredir.n = list(0);
11835                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11836                 t = TRP;
11837                 break;
11838         case TBEGIN:
11839                 n1 = list(0);
11840                 t = TEND;
11841                 break;
11842         IF_BASH_FUNCTION(case TFUNCTION:)
11843         case TWORD:
11844         case TREDIR:
11845                 tokpushback = 1;
11846                 return simplecmd();
11847         }
11848
11849         if (readtoken() != t)
11850                 raise_error_unexpected_syntax(t);
11851
11852  redir:
11853         /* Now check for redirection which may follow command */
11854         checkkwd = CHKKWD | CHKALIAS;
11855         rpp = rpp2;
11856         while (readtoken() == TREDIR) {
11857                 *rpp = n2 = redirnode;
11858                 rpp = &n2->nfile.next;
11859                 parsefname();
11860         }
11861         tokpushback = 1;
11862         *rpp = NULL;
11863         if (redir) {
11864                 if (n1->type != NSUBSHELL) {
11865                         n2 = stzalloc(sizeof(struct nredir));
11866                         n2->type = NREDIR;
11867                         n2->nredir.linno = savelinno;
11868                         n2->nredir.n = n1;
11869                         n1 = n2;
11870                 }
11871                 n1->nredir.redirect = redir;
11872         }
11873         return n1;
11874 }
11875
11876 #if BASH_DOLLAR_SQUOTE
11877 static int
11878 decode_dollar_squote(void)
11879 {
11880         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11881         int c, cnt;
11882         char *p;
11883         char buf[4];
11884
11885         c = pgetc();
11886         p = strchr(C_escapes, c);
11887         if (p) {
11888                 buf[0] = c;
11889                 p = buf;
11890                 cnt = 3;
11891                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11892                         do {
11893                                 c = pgetc();
11894                                 *++p = c;
11895                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11896                         pungetc();
11897                 } else if (c == 'x') { /* \xHH */
11898                         do {
11899                                 c = pgetc();
11900                                 *++p = c;
11901                         } while (isxdigit(c) && --cnt);
11902                         pungetc();
11903                         if (cnt == 3) { /* \x but next char is "bad" */
11904                                 c = 'x';
11905                                 goto unrecognized;
11906                         }
11907                 } else { /* simple seq like \\ or \t */
11908                         p++;
11909                 }
11910                 *p = '\0';
11911                 p = buf;
11912                 c = bb_process_escape_sequence((void*)&p);
11913         } else { /* unrecognized "\z": print both chars unless ' or " */
11914                 if (c != '\'' && c != '"') {
11915  unrecognized:
11916                         c |= 0x100; /* "please encode \, then me" */
11917                 }
11918         }
11919         return c;
11920 }
11921 #endif
11922
11923 /* Used by expandstr to get here-doc like behaviour. */
11924 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11925
11926 static ALWAYS_INLINE int
11927 realeofmark(const char *eofmark)
11928 {
11929         return eofmark && eofmark != FAKEEOFMARK;
11930 }
11931
11932 /*
11933  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11934  * is not NULL, read a here document.  In the latter case, eofmark is the
11935  * word which marks the end of the document and striptabs is true if
11936  * leading tabs should be stripped from the document.  The argument c
11937  * is the first character of the input token or document.
11938  *
11939  * Because C does not have internal subroutines, I have simulated them
11940  * using goto's to implement the subroutine linkage.  The following macros
11941  * will run code that appears at the end of readtoken1.
11942  */
11943 #define CHECKEND()      {goto checkend; checkend_return:;}
11944 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11945 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11946 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11947 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11948 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11949 static int
11950 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11951 {
11952         /* NB: syntax parameter fits into smallint */
11953         /* c parameter is an unsigned char or PEOF or PEOA */
11954         char *out;
11955         size_t len;
11956         struct nodelist *bqlist;
11957         smallint quotef;
11958         smallint oldstyle;
11959         smallint pssyntax;   /* we are expanding a prompt string */
11960         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11961         /* syntax stack */
11962         struct synstack synbase = { };
11963         struct synstack *synstack = &synbase;
11964
11965 #if ENABLE_ASH_EXPAND_PRMT
11966         pssyntax = (syntax == PSSYNTAX);
11967         if (pssyntax)
11968                 syntax = DQSYNTAX;
11969 #else
11970         pssyntax = 0; /* constant */
11971 #endif
11972         synstack->syntax = syntax;
11973
11974         if (syntax == DQSYNTAX)
11975                 synstack->dblquote = 1;
11976         quotef = 0;
11977         bqlist = NULL;
11978
11979         STARTSTACKSTR(out);
11980  loop:
11981         /* For each line, until end of word */
11982         CHECKEND();     /* set c to PEOF if at end of here document */
11983         for (;;) {      /* until end of line or end of word */
11984                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11985                 switch (SIT(c, synstack->syntax)) {
11986                 case CNL:       /* '\n' */
11987                         if (synstack->syntax == BASESYNTAX)
11988                                 goto endword;   /* exit outer loop */
11989                         USTPUTC(c, out);
11990                         nlprompt();
11991                         c = pgetc();
11992                         goto loop;              /* continue outer loop */
11993                 case CWORD:
11994                         USTPUTC(c, out);
11995                         break;
11996                 case CCTL:
11997 #if BASH_DOLLAR_SQUOTE
11998                         if (c == '\\' && bash_dollar_squote) {
11999                                 c = decode_dollar_squote();
12000                                 if (c == '\0') {
12001                                         /* skip $'\000', $'\x00' (like bash) */
12002                                         break;
12003                                 }
12004                                 if (c & 0x100) {
12005                                         /* Unknown escape. Encode as '\z' */
12006                                         c = (unsigned char)c;
12007                                         if (eofmark == NULL || synstack->dblquote)
12008                                                 USTPUTC(CTLESC, out);
12009                                         USTPUTC('\\', out);
12010                                 }
12011                         }
12012 #endif
12013                         if (!eofmark || synstack->dblquote || synstack->varnest)
12014                                 USTPUTC(CTLESC, out);
12015                         USTPUTC(c, out);
12016                         break;
12017                 case CBACK:     /* backslash */
12018                         c = pgetc_without_PEOA();
12019                         if (c == PEOF) {
12020                                 USTPUTC(CTLESC, out);
12021                                 USTPUTC('\\', out);
12022                                 pungetc();
12023                         } else if (c == '\n') {
12024                                 nlprompt();
12025                         } else {
12026                                 if (pssyntax && c == '$') {
12027                                         USTPUTC(CTLESC, out);
12028                                         USTPUTC('\\', out);
12029                                 }
12030                                 /* Backslash is retained if we are in "str"
12031                                  * and next char isn't dquote-special.
12032                                  */
12033                                 if (synstack->dblquote
12034                                  && c != '\\'
12035                                  && c != '`'
12036                                  && c != '$'
12037                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12038                                  && (c != '}' || !synstack->varnest)
12039                                 ) {
12040                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12041                                         USTPUTC('\\', out);
12042                                 }
12043                                 USTPUTC(CTLESC, out);
12044                                 USTPUTC(c, out);
12045                                 quotef = 1;
12046                         }
12047                         break;
12048                 case CSQUOTE:
12049                         synstack->syntax = SQSYNTAX;
12050  quotemark:
12051                         if (eofmark == NULL) {
12052                                 USTPUTC(CTLQUOTEMARK, out);
12053                         }
12054                         break;
12055                 case CDQUOTE:
12056                         synstack->syntax = DQSYNTAX;
12057                         synstack->dblquote = 1;
12058  toggledq:
12059                         if (synstack->varnest)
12060                                 synstack->innerdq ^= 1;
12061                         goto quotemark;
12062                 case CENDQUOTE:
12063                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12064                         if (eofmark != NULL && synstack->varnest == 0) {
12065                                 USTPUTC(c, out);
12066                                 break;
12067                         }
12068
12069                         if (synstack->dqvarnest == 0) {
12070                                 synstack->syntax = BASESYNTAX;
12071                                 synstack->dblquote = 0;
12072                         }
12073
12074                         quotef = 1;
12075
12076                         if (c == '"')
12077                                 goto toggledq;
12078
12079                         goto quotemark;
12080                 case CVAR:      /* '$' */
12081                         PARSESUB();             /* parse substitution */
12082                         break;
12083                 case CENDVAR:   /* '}' */
12084                         if (!synstack->innerdq && synstack->varnest > 0) {
12085                                 if (!--synstack->varnest && synstack->varpushed)
12086                                         synstack_pop(&synstack);
12087                                 else if (synstack->dqvarnest > 0)
12088                                         synstack->dqvarnest--;
12089                                 c = CTLENDVAR;
12090                         }
12091                         USTPUTC(c, out);
12092                         break;
12093 #if ENABLE_FEATURE_SH_MATH
12094                 case CLP:       /* '(' in arithmetic */
12095                         synstack->parenlevel++;
12096                         USTPUTC(c, out);
12097                         break;
12098                 case CRP:       /* ')' in arithmetic */
12099                         if (synstack->parenlevel > 0) {
12100                                 synstack->parenlevel--;
12101                         } else {
12102                                 if (pgetc_eatbnl() == ')') {
12103                                         c = CTLENDARI;
12104                                         synstack_pop(&synstack);
12105                                 } else {
12106                                         /*
12107                                          * unbalanced parens
12108                                          * (don't 2nd guess - no error)
12109                                          */
12110                                         pungetc();
12111                                 }
12112                         }
12113                         USTPUTC(c, out);
12114                         break;
12115 #endif
12116                 case CBQUOTE:   /* '`' */
12117                         if (checkkwd & CHKEOFMARK) {
12118                                 quotef = 1;
12119                                 USTPUTC('`', out);
12120                                 break;
12121                         }
12122
12123                         PARSEBACKQOLD();
12124                         break;
12125                 case CENDFILE:
12126                         goto endword;           /* exit outer loop */
12127                 case CIGN:
12128                         break;
12129                 default:
12130                         if (synstack->varnest == 0) {
12131 #if BASH_REDIR_OUTPUT
12132                                 if (c == '&') {
12133 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12134                                         if (pgetc() == '>')
12135                                                 c = 0x100 + '>'; /* flag &> */
12136                                         pungetc();
12137                                 }
12138 #endif
12139                                 goto endword;   /* exit outer loop */
12140                         }
12141                         IF_ASH_ALIAS(if (c != PEOA))
12142                                 USTPUTC(c, out);
12143                 }
12144                 c = pgetc();
12145         } /* for (;;) */
12146  endword:
12147
12148 #if ENABLE_FEATURE_SH_MATH
12149         if (synstack->syntax == ARISYNTAX)
12150                 raise_error_syntax("missing '))'");
12151 #endif
12152         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12153                 raise_error_syntax("unterminated quoted string");
12154         if (synstack->varnest != 0) {
12155                 /* { */
12156                 raise_error_syntax("missing '}'");
12157         }
12158         USTPUTC('\0', out);
12159         len = out - (char *)stackblock();
12160         out = stackblock();
12161         if (eofmark == NULL) {
12162                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12163                  && quotef == 0
12164                 ) {
12165                         if (isdigit_str9(out)) {
12166                                 PARSEREDIR(); /* passed as params: out, c */
12167                                 lasttoken = TREDIR;
12168                                 return lasttoken;
12169                         }
12170                         /* else: non-number X seen, interpret it
12171                          * as "NNNX>file" = "NNNX >file" */
12172                 }
12173                 pungetc();
12174         }
12175         quoteflag = quotef;
12176         backquotelist = bqlist;
12177         grabstackblock(len);
12178         wordtext = out;
12179         lasttoken = TWORD;
12180         return lasttoken;
12181 /* end of readtoken routine */
12182
12183 /*
12184  * Check to see whether we are at the end of the here document.  When this
12185  * is called, c is set to the first character of the next input line.  If
12186  * we are at the end of the here document, this routine sets the c to PEOF.
12187  */
12188 checkend: {
12189         if (realeofmark(eofmark)) {
12190                 int markloc;
12191                 char *p;
12192
12193 #if ENABLE_ASH_ALIAS
12194                 if (c == PEOA)
12195                         c = pgetc_without_PEOA();
12196 #endif
12197                 if (striptabs) {
12198                         while (c == '\t') {
12199                                 c = pgetc_without_PEOA();
12200                         }
12201                 }
12202
12203                 markloc = out - (char *)stackblock();
12204                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12205                         if (c != *p)
12206                                 goto more_heredoc;
12207
12208                         c = pgetc_without_PEOA();
12209                 }
12210
12211                 if (c == '\n' || c == PEOF) {
12212                         c = PEOF;
12213                         g_parsefile->linno++;
12214                         needprompt = doprompt;
12215                 } else {
12216                         int len_here;
12217
12218  more_heredoc:
12219                         p = (char *)stackblock() + markloc + 1;
12220                         len_here = out - p;
12221
12222                         if (len_here) {
12223                                 len_here -= (c >= PEOF);
12224                                 c = p[-1];
12225
12226                                 if (len_here) {
12227                                         char *str;
12228
12229                                         str = alloca(len_here + 1);
12230                                         *(char *)mempcpy(str, p, len_here) = '\0';
12231
12232                                         pushstring(str, NULL);
12233                                 }
12234                         }
12235                 }
12236
12237                 STADJUST((char *)stackblock() + markloc - out, out);
12238         }
12239         goto checkend_return;
12240 }
12241
12242 /*
12243  * Parse a redirection operator.  The variable "out" points to a string
12244  * specifying the fd to be redirected.  The variable "c" contains the
12245  * first character of the redirection operator.
12246  */
12247 parseredir: {
12248         /* out is already checked to be a valid number or "" */
12249         int fd = (*out == '\0' ? -1 : atoi(out));
12250         union node *np;
12251
12252         np = stzalloc(sizeof(struct nfile));
12253         if (c == '>') {
12254                 np->nfile.fd = 1;
12255                 c = pgetc_eatbnl();
12256                 if (c == '>')
12257                         np->type = NAPPEND;
12258                 else if (c == '|')
12259                         np->type = NCLOBBER;
12260                 else if (c == '&')
12261                         np->type = NTOFD;
12262                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12263                 else {
12264                         np->type = NTO;
12265                         pungetc();
12266                 }
12267         }
12268 #if BASH_REDIR_OUTPUT
12269         else if (c == 0x100 + '>') { /* this flags &> redirection */
12270                 np->nfile.fd = 1;
12271                 pgetc(); /* this is '>', no need to check */
12272                 np->type = NTO2;
12273         }
12274 #endif
12275         else { /* c == '<' */
12276                 /*np->nfile.fd = 0; - stzalloc did it */
12277                 c = pgetc_eatbnl();
12278                 switch (c) {
12279                 case '<':
12280                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12281                                 np = stzalloc(sizeof(struct nhere));
12282                                 /*np->nfile.fd = 0; - stzalloc did it */
12283                         }
12284                         np->type = NHERE;
12285                         heredoc = stzalloc(sizeof(struct heredoc));
12286                         heredoc->here = np;
12287                         c = pgetc_eatbnl();
12288                         if (c == '-') {
12289                                 heredoc->striptabs = 1;
12290                         } else {
12291                                 /*heredoc->striptabs = 0; - stzalloc did it */
12292                                 pungetc();
12293                         }
12294                         break;
12295
12296                 case '&':
12297                         np->type = NFROMFD;
12298                         break;
12299
12300                 case '>':
12301                         np->type = NFROMTO;
12302                         break;
12303
12304                 default:
12305                         np->type = NFROM;
12306                         pungetc();
12307                         break;
12308                 }
12309         }
12310         if (fd >= 0)
12311                 np->nfile.fd = fd;
12312         redirnode = np;
12313         goto parseredir_return;
12314 }
12315
12316 /*
12317  * Parse a substitution.  At this point, we have read the dollar sign
12318  * and nothing else.
12319  */
12320
12321 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12322  * (assuming ascii char codes, as the original implementation did) */
12323 #define is_special(c) \
12324         (((unsigned)(c) - 33 < 32) \
12325                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12326 parsesub: {
12327         unsigned char subtype;
12328         int typeloc;
12329
12330         c = pgetc_eatbnl();
12331         if ((checkkwd & CHKEOFMARK)
12332          || c > 255 /* PEOA or PEOF */
12333          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12334         ) {
12335 #if BASH_DOLLAR_SQUOTE
12336                 if (synstack->syntax != DQSYNTAX && c == '\'')
12337                         bash_dollar_squote = 1;
12338                 else
12339 #endif
12340                         USTPUTC('$', out);
12341                 pungetc();
12342         } else if (c == '(') {
12343                 /* $(command) or $((arith)) */
12344                 if (pgetc_eatbnl() == '(') {
12345 #if ENABLE_FEATURE_SH_MATH
12346                         PARSEARITH();
12347 #else
12348                         raise_error_syntax("support for $((arith)) is disabled");
12349 #endif
12350                 } else {
12351                         pungetc();
12352                         PARSEBACKQNEW();
12353                 }
12354         } else {
12355                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12356                 smalluint newsyn = synstack->syntax;
12357
12358                 USTPUTC(CTLVAR, out);
12359                 typeloc = out - (char *)stackblock();
12360                 STADJUST(1, out);
12361                 subtype = VSNORMAL;
12362                 if (c == '{') {
12363                         c = pgetc_eatbnl();
12364                         subtype = 0;
12365                 }
12366  varname:
12367                 if (is_name(c)) {
12368                         /* $[{[#]]NAME[}] */
12369                         do {
12370                                 STPUTC(c, out);
12371                                 c = pgetc_eatbnl();
12372                         } while (is_in_name(c));
12373                 } else if (isdigit(c)) {
12374                         /* $[{[#]]NUM[}] */
12375                         do {
12376                                 STPUTC(c, out);
12377                                 c = pgetc_eatbnl();
12378                         } while (isdigit(c));
12379                 } else {
12380                         /* $[{[#]]<specialchar>[}] */
12381                         int cc = c;
12382
12383                         c = pgetc_eatbnl();
12384                         if (!subtype && cc == '#') {
12385                                 subtype = VSLENGTH;
12386                                 if (c == '_' || isalnum(c))
12387                                         goto varname;
12388                                 cc = c;
12389                                 c = pgetc_eatbnl();
12390                                 if (cc == '}' || c != '}') {
12391                                         pungetc();
12392                                         subtype = 0;
12393                                         c = cc;
12394                                         cc = '#';
12395                                 }
12396                         }
12397
12398                         if (!is_special(cc)) {
12399                                 if (subtype == VSLENGTH)
12400                                         subtype = 0;
12401                                 goto badsub;
12402                         }
12403
12404                         USTPUTC(cc, out);
12405                 }
12406
12407                 if (c != '}' && subtype == VSLENGTH) {
12408                         /* ${#VAR didn't end with } */
12409                         goto badsub;
12410                 }
12411
12412                 if (subtype == 0) {
12413                         static const char types[] ALIGN1 = "}-+?=";
12414                         /* ${VAR...} but not $VAR or ${#VAR} */
12415                         /* c == first char after VAR */
12416                         int cc = c;
12417
12418                         switch (c) {
12419                         case ':':
12420                                 c = pgetc_eatbnl();
12421 #if BASH_SUBSTR
12422                                 /* This check is only needed to not misinterpret
12423                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12424                                  * constructs.
12425                                  */
12426                                 if (!strchr(types, c)) {
12427                                         subtype = VSSUBSTR;
12428                                         pungetc();
12429                                         break; /* "goto badsub" is bigger (!) */
12430                                 }
12431 #endif
12432                                 subtype = VSNUL;
12433                                 /*FALLTHROUGH*/
12434                         default: {
12435                                 const char *p = strchr(types, c);
12436                                 if (p == NULL)
12437                                         break;
12438                                 subtype |= p - types + VSNORMAL;
12439                                 break;
12440                         }
12441                         case '%':
12442                         case '#':
12443                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12444                                 c = pgetc_eatbnl();
12445                                 if (c == cc)
12446                                         subtype++;
12447                                 else
12448                                         pungetc();
12449
12450                                 newsyn = BASESYNTAX;
12451                                 break;
12452 #if BASH_PATTERN_SUBST
12453                         case '/':
12454                                 /* ${v/[/]pattern/repl} */
12455 //TODO: encode pattern and repl separately.
12456 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12457 // are broken (should print "ONE")
12458                                 subtype = VSREPLACE;
12459                                 newsyn = BASESYNTAX;
12460                                 c = pgetc_eatbnl();
12461                                 if (c != '/')
12462                                         goto badsub;
12463                                 subtype++; /* VSREPLACEALL */
12464                                 break;
12465 #endif
12466                         }
12467                 } else {
12468  badsub:
12469                         pungetc();
12470                 }
12471
12472                 if (newsyn == ARISYNTAX)
12473                         newsyn = DQSYNTAX;
12474
12475                 if ((newsyn != synstack->syntax || synstack->innerdq)
12476                  && subtype != VSNORMAL
12477                 ) {
12478                         synstack_push(&synstack,
12479                                 synstack->prev ?: alloca(sizeof(*synstack)),
12480                                 newsyn);
12481
12482                         synstack->varpushed = 1;
12483                         synstack->dblquote = newsyn != BASESYNTAX;
12484                 }
12485
12486                 ((unsigned char *)stackblock())[typeloc] = subtype;
12487                 if (subtype != VSNORMAL) {
12488                         synstack->varnest++;
12489                         if (synstack->dblquote)
12490                                 synstack->dqvarnest++;
12491                 }
12492                 STPUTC('=', out);
12493         }
12494         goto parsesub_return;
12495 }
12496
12497 /*
12498  * Called to parse command substitutions.  Newstyle is set if the command
12499  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12500  * list of commands (passed by reference), and savelen is the number of
12501  * characters on the top of the stack which must be preserved.
12502  */
12503 parsebackq: {
12504         struct nodelist **nlpp;
12505         union node *n;
12506         char *str;
12507         size_t savelen;
12508         smallint saveprompt = 0;
12509
12510         str = NULL;
12511         savelen = out - (char *)stackblock();
12512         if (savelen > 0) {
12513                 /*
12514                  * FIXME: this can allocate very large block on stack and SEGV.
12515                  * Example:
12516                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12517                  * allocates 100kb for every command subst. With about
12518                  * a hundred command substitutions stack overflows.
12519                  * With larger prepended string, SEGV happens sooner.
12520                  */
12521                 str = alloca(savelen);
12522                 memcpy(str, stackblock(), savelen);
12523         }
12524
12525         if (oldstyle) {
12526                 /* We must read until the closing backquote, giving special
12527                  * treatment to some slashes, and then push the string and
12528                  * reread it as input, interpreting it normally.
12529                  */
12530                 char *pout;
12531                 size_t psavelen;
12532                 char *pstr;
12533
12534                 STARTSTACKSTR(pout);
12535                 for (;;) {
12536                         int pc;
12537
12538                         setprompt_if(needprompt, 2);
12539                         pc = pgetc_eatbnl();
12540                         switch (pc) {
12541                         case '`':
12542                                 goto done;
12543
12544                         case '\\':
12545                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12546                                 if (pc != '\\' && pc != '`' && pc != '$'
12547                                  && (!synstack->dblquote || pc != '"')
12548                                 ) {
12549                                         STPUTC('\\', pout);
12550                                 }
12551                                 if (pc <= 255 /* not PEOA or PEOF */) {
12552                                         break;
12553                                 }
12554                                 /* fall through */
12555
12556                         case PEOF:
12557                         IF_ASH_ALIAS(case PEOA:)
12558                                 raise_error_syntax("EOF in backquote substitution");
12559
12560                         case '\n':
12561                                 nlnoprompt();
12562                                 break;
12563
12564                         default:
12565                                 break;
12566                         }
12567                         STPUTC(pc, pout);
12568                 }
12569  done:
12570                 STPUTC('\0', pout);
12571                 psavelen = pout - (char *)stackblock();
12572                 if (psavelen > 0) {
12573                         pstr = grabstackstr(pout);
12574                         setinputstring(pstr);
12575                 }
12576         }
12577         nlpp = &bqlist;
12578         while (*nlpp)
12579                 nlpp = &(*nlpp)->next;
12580         *nlpp = stzalloc(sizeof(**nlpp));
12581         /* (*nlpp)->next = NULL; - stzalloc did it */
12582
12583         if (oldstyle) {
12584                 saveprompt = doprompt;
12585                 doprompt = 0;
12586         }
12587
12588         n = list(2);
12589
12590         if (oldstyle)
12591                 doprompt = saveprompt;
12592         else if (readtoken() != TRP)
12593                 raise_error_unexpected_syntax(TRP);
12594
12595         (*nlpp)->n = n;
12596         if (oldstyle) {
12597                 /*
12598                  * Start reading from old file again, ignoring any pushed back
12599                  * tokens left from the backquote parsing
12600                  */
12601                 popfile();
12602                 tokpushback = 0;
12603         }
12604         while (stackblocksize() <= savelen)
12605                 growstackblock();
12606         STARTSTACKSTR(out);
12607         if (str) {
12608                 memcpy(out, str, savelen);
12609                 STADJUST(savelen, out);
12610         }
12611         USTPUTC(CTLBACKQ, out);
12612         if (oldstyle)
12613                 goto parsebackq_oldreturn;
12614         goto parsebackq_newreturn;
12615 }
12616
12617 #if ENABLE_FEATURE_SH_MATH
12618 /*
12619  * Parse an arithmetic expansion (indicate start of one and set state)
12620  */
12621 parsearith: {
12622
12623         synstack_push(&synstack,
12624                         synstack->prev ?: alloca(sizeof(*synstack)),
12625                         ARISYNTAX);
12626         synstack->dblquote = 1;
12627         USTPUTC(CTLARI, out);
12628         goto parsearith_return;
12629 }
12630 #endif
12631 } /* end of readtoken */
12632
12633 /*
12634  * Read the next input token.
12635  * If the token is a word, we set backquotelist to the list of cmds in
12636  *      backquotes.  We set quoteflag to true if any part of the word was
12637  *      quoted.
12638  * If the token is TREDIR, then we set redirnode to a structure containing
12639  *      the redirection.
12640  *
12641  * [Change comment:  here documents and internal procedures]
12642  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12643  *  word parsing code into a separate routine.  In this case, readtoken
12644  *  doesn't need to have any internal procedures, but parseword does.
12645  *  We could also make parseoperator in essence the main routine, and
12646  *  have parseword (readtoken1?) handle both words and redirection.]
12647  */
12648 #define NEW_xxreadtoken
12649 #ifdef NEW_xxreadtoken
12650 /* singles must be first! */
12651 static const char xxreadtoken_chars[7] ALIGN1 = {
12652         '\n', '(', ')', /* singles */
12653         '&', '|', ';',  /* doubles */
12654         0
12655 };
12656
12657 #define xxreadtoken_singles 3
12658 #define xxreadtoken_doubles 3
12659
12660 static const char xxreadtoken_tokens[] ALIGN1 = {
12661         TNL, TLP, TRP,          /* only single occurrence allowed */
12662         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12663         TEOF,                   /* corresponds to trailing nul */
12664         TAND, TOR, TENDCASE     /* if double occurrence */
12665 };
12666
12667 static int
12668 xxreadtoken(void)
12669 {
12670         int c;
12671
12672         if (tokpushback) {
12673                 tokpushback = 0;
12674                 return lasttoken;
12675         }
12676         setprompt_if(needprompt, 2);
12677         for (;;) {                      /* until token or start of word found */
12678                 c = pgetc_eatbnl();
12679                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12680                         continue;
12681
12682                 if (c == '#') {
12683                         while ((c = pgetc()) != '\n' && c != PEOF)
12684                                 continue;
12685                         pungetc();
12686                 } else if (c == '\\') {
12687                         break; /* return readtoken1(...) */
12688                 } else {
12689                         const char *p;
12690
12691                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12692                         if (c != PEOF) {
12693                                 if (c == '\n') {
12694                                         nlnoprompt();
12695                                 }
12696
12697                                 p = strchr(xxreadtoken_chars, c);
12698                                 if (p == NULL)
12699                                         break; /* return readtoken1(...) */
12700
12701                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12702                                         int cc = pgetc_eatbnl();
12703                                         if (cc == c) {    /* double occurrence? */
12704                                                 p += xxreadtoken_doubles + 1;
12705                                         } else {
12706                                                 pungetc();
12707 #if BASH_REDIR_OUTPUT
12708                                                 if (c == '&' && cc == '>') /* &> */
12709                                                         break; /* return readtoken1(...) */
12710 #endif
12711                                         }
12712                                 }
12713                         }
12714                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12715                         return lasttoken;
12716                 }
12717         } /* for (;;) */
12718
12719         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12720 }
12721 #else /* old xxreadtoken */
12722 #define RETURN(token)   return lasttoken = token
12723 static int
12724 xxreadtoken(void)
12725 {
12726         int c;
12727
12728         if (tokpushback) {
12729                 tokpushback = 0;
12730                 return lasttoken;
12731         }
12732         setprompt_if(needprompt, 2);
12733         for (;;) {      /* until token or start of word found */
12734                 c = pgetc_eatbnl();
12735                 switch (c) {
12736                 case ' ': case '\t':
12737                 IF_ASH_ALIAS(case PEOA:)
12738                         continue;
12739                 case '#':
12740                         while ((c = pgetc()) != '\n' && c != PEOF)
12741                                 continue;
12742                         pungetc();
12743                         continue;
12744                 case '\n':
12745                         nlnoprompt();
12746                         RETURN(TNL);
12747                 case PEOF:
12748                         RETURN(TEOF);
12749                 case '&':
12750                         if (pgetc_eatbnl() == '&')
12751                                 RETURN(TAND);
12752                         pungetc();
12753                         RETURN(TBACKGND);
12754                 case '|':
12755                         if (pgetc_eatbnl() == '|')
12756                                 RETURN(TOR);
12757                         pungetc();
12758                         RETURN(TPIPE);
12759                 case ';':
12760                         if (pgetc_eatbnl() == ';')
12761                                 RETURN(TENDCASE);
12762                         pungetc();
12763                         RETURN(TSEMI);
12764                 case '(':
12765                         RETURN(TLP);
12766                 case ')':
12767                         RETURN(TRP);
12768                 }
12769                 break;
12770         }
12771         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12772 #undef RETURN
12773 }
12774 #endif /* old xxreadtoken */
12775
12776 static int
12777 readtoken(void)
12778 {
12779         int t;
12780         int kwd = checkkwd;
12781 #if DEBUG
12782         smallint alreadyseen = tokpushback;
12783 #endif
12784
12785 #if ENABLE_ASH_ALIAS
12786  top:
12787 #endif
12788
12789         t = xxreadtoken();
12790
12791         /*
12792          * eat newlines
12793          */
12794         if (kwd & CHKNL) {
12795                 while (t == TNL) {
12796                         parseheredoc();
12797                         t = xxreadtoken();
12798                 }
12799         }
12800
12801         if (t != TWORD || quoteflag) {
12802                 goto out;
12803         }
12804
12805         /*
12806          * check for keywords
12807          */
12808         if (kwd & CHKKWD) {
12809                 const char *const *pp;
12810
12811                 pp = findkwd(wordtext);
12812                 if (pp) {
12813                         lasttoken = t = pp - tokname_array;
12814                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12815                         goto out;
12816                 }
12817         }
12818
12819         if (checkkwd & CHKALIAS) {
12820 #if ENABLE_ASH_ALIAS
12821                 struct alias *ap;
12822                 ap = lookupalias(wordtext, 1);
12823                 if (ap != NULL) {
12824                         if (*ap->val) {
12825                                 pushstring(ap->val, ap);
12826                         }
12827                         goto top;
12828                 }
12829 #endif
12830         }
12831  out:
12832         checkkwd = 0;
12833 #if DEBUG
12834         if (!alreadyseen)
12835                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12836         else
12837                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12838 #endif
12839         return t;
12840 }
12841
12842 static int
12843 peektoken(void)
12844 {
12845         int t;
12846
12847         t = readtoken();
12848         tokpushback = 1;
12849         return t;
12850 }
12851
12852 /*
12853  * Read and parse a command.  Returns NODE_EOF on end of file.
12854  * (NULL is a valid parse tree indicating a blank line.)
12855  */
12856 static union node *
12857 parsecmd(int interact)
12858 {
12859         tokpushback = 0;
12860         checkkwd = 0;
12861         heredoclist = 0;
12862         doprompt = interact;
12863         setprompt_if(doprompt, doprompt);
12864         needprompt = 0;
12865         return list(1);
12866 }
12867
12868 /*
12869  * Input any here documents.
12870  */
12871 static void
12872 parseheredoc(void)
12873 {
12874         struct heredoc *here;
12875         union node *n;
12876
12877         here = heredoclist;
12878         heredoclist = NULL;
12879
12880         while (here) {
12881                 setprompt_if(needprompt, 2);
12882                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12883                                 here->eofmark, here->striptabs);
12884                 n = stzalloc(sizeof(struct narg));
12885                 n->narg.type = NARG;
12886                 /*n->narg.next = NULL; - stzalloc did it */
12887                 n->narg.text = wordtext;
12888                 n->narg.backquote = backquotelist;
12889                 here->here->nhere.doc = n;
12890                 here = here->next;
12891         }
12892 }
12893
12894
12895 static const char *
12896 expandstr(const char *ps, int syntax_type)
12897 {
12898         union node n;
12899         int saveprompt;
12900
12901         /* XXX Fix (char *) cast. */
12902         setinputstring((char *)ps);
12903
12904         saveprompt = doprompt;
12905         doprompt = 0;
12906
12907         /* readtoken1() might die horribly.
12908          * Try a prompt with syntactically wrong command:
12909          * PS1='$(date "+%H:%M:%S) > '
12910          */
12911         {
12912                 volatile int saveint;
12913                 struct jmploc *volatile savehandler = exception_handler;
12914                 struct jmploc jmploc;
12915                 SAVE_INT(saveint);
12916                 if (setjmp(jmploc.loc) == 0) {
12917                         exception_handler = &jmploc;
12918                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12919                 }
12920                 exception_handler = savehandler;
12921                 RESTORE_INT(saveint);
12922         }
12923
12924         doprompt = saveprompt;
12925
12926         popfile();
12927
12928         n.narg.type = NARG;
12929         n.narg.next = NULL;
12930         n.narg.text = wordtext;
12931         n.narg.backquote = backquotelist;
12932
12933         expandarg(&n, NULL, EXP_QUOTED);
12934         return stackblock();
12935 }
12936
12937 static inline int
12938 parser_eof(void)
12939 {
12940         return tokpushback && lasttoken == TEOF;
12941 }
12942
12943 /*
12944  * Execute a command or commands contained in a string.
12945  */
12946 static int
12947 evalstring(char *s, int flags)
12948 {
12949         struct jmploc *volatile savehandler;
12950         struct jmploc jmploc;
12951         int ex;
12952
12953         union node *n;
12954         struct stackmark smark;
12955         int status;
12956
12957         s = sstrdup(s);
12958         setinputstring(s);
12959         setstackmark(&smark);
12960
12961         status = 0;
12962         /* On exception inside execution loop, we must popfile().
12963          * Try interactively:
12964          *      readonly a=a
12965          *      command eval "a=b"  # throws "is read only" error
12966          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12967          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12968          */
12969         savehandler = exception_handler;
12970         ex = setjmp(jmploc.loc);
12971         if (ex)
12972                 goto out;
12973         exception_handler = &jmploc;
12974
12975         while ((n = parsecmd(0)) != NODE_EOF) {
12976                 int i;
12977
12978                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12979                 if (n)
12980                         status = i;
12981                 popstackmark(&smark);
12982                 if (evalskip)
12983                         break;
12984         }
12985  out:
12986         popstackmark(&smark);
12987         popfile();
12988         stunalloc(s);
12989
12990         exception_handler = savehandler;
12991         if (ex)
12992                 longjmp(exception_handler->loc, ex);
12993
12994         return status;
12995 }
12996
12997 /*
12998  * The eval command.
12999  */
13000 static int FAST_FUNC
13001 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13002 {
13003         char *p;
13004         char *concat;
13005
13006         if (argv[1]) {
13007                 p = argv[1];
13008                 argv += 2;
13009                 if (argv[0]) {
13010                         STARTSTACKSTR(concat);
13011                         for (;;) {
13012                                 concat = stack_putstr(p, concat);
13013                                 p = *argv++;
13014                                 if (p == NULL)
13015                                         break;
13016                                 STPUTC(' ', concat);
13017                         }
13018                         STPUTC('\0', concat);
13019                         p = grabstackstr(concat);
13020                 }
13021                 return evalstring(p, flags & EV_TESTED);
13022         }
13023         return 0;
13024 }
13025
13026 /*
13027  * Read and execute commands.
13028  * "Top" is nonzero for the top level command loop;
13029  * it turns on prompting if the shell is interactive.
13030  */
13031 static int
13032 cmdloop(int top)
13033 {
13034         union node *n;
13035         struct stackmark smark;
13036         int inter;
13037         int status = 0;
13038         int numeof = 0;
13039
13040         TRACE(("cmdloop(%d) called\n", top));
13041         for (;;) {
13042                 int skip;
13043
13044                 setstackmark(&smark);
13045 #if JOBS
13046                 if (doing_jobctl)
13047                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13048 #endif
13049                 inter = 0;
13050                 if (iflag && top) {
13051                         inter++;
13052                         chkmail();
13053                 }
13054                 n = parsecmd(inter);
13055 #if DEBUG
13056                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13057                         showtree(n);
13058 #endif
13059                 if (n == NODE_EOF) {
13060                         if (!top || numeof >= 50)
13061                                 break;
13062                         if (!stoppedjobs()) {
13063                                 if (!Iflag)
13064                                         break;
13065                                 out2str("\nUse \"exit\" to leave shell.\n");
13066                         }
13067                         numeof++;
13068                 } else if (nflag == 0) {
13069                         int i;
13070
13071                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13072                         job_warning >>= 1;
13073                         numeof = 0;
13074                         i = evaltree(n, 0);
13075                         if (n)
13076                                 status = i;
13077                 }
13078                 popstackmark(&smark);
13079                 skip = evalskip;
13080
13081                 if (skip) {
13082                         evalskip &= ~SKIPFUNC;
13083                         break;
13084                 }
13085         }
13086         return status;
13087 }
13088
13089 /*
13090  * Take commands from a file.  To be compatible we should do a path
13091  * search for the file, which is necessary to find sub-commands.
13092  */
13093 static char *
13094 find_dot_file(char *name)
13095 {
13096         char *fullname;
13097         const char *path = pathval();
13098         struct stat statb;
13099
13100         /* don't try this for absolute or relative paths */
13101         if (strchr(name, '/'))
13102                 return name;
13103
13104         while ((fullname = path_advance(&path, name)) != NULL) {
13105                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13106                         /*
13107                          * Don't bother freeing here, since it will
13108                          * be freed by the caller.
13109                          */
13110                         return fullname;
13111                 }
13112                 if (fullname != name)
13113                         stunalloc(fullname);
13114         }
13115         /* not found in PATH */
13116
13117 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13118         return name;
13119 #else
13120         ash_msg_and_raise_error("%s: not found", name);
13121         /* NOTREACHED */
13122 #endif
13123 }
13124
13125 static int FAST_FUNC
13126 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13127 {
13128         /* "false; . empty_file; echo $?" should print 0, not 1: */
13129         int status = 0;
13130         char *fullname;
13131         char **argv;
13132         char *args_need_save;
13133         volatile struct shparam saveparam;
13134
13135 //???
13136 //      struct strlist *sp;
13137 //      for (sp = cmdenviron; sp; sp = sp->next)
13138 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13139
13140         nextopt(nullstr); /* handle possible "--" */
13141         argv = argptr;
13142
13143         if (!argv[0]) {
13144                 /* bash says: "bash: .: filename argument required" */
13145                 return 2; /* bash compat */
13146         }
13147
13148         /* This aborts if file isn't found, which is POSIXly correct.
13149          * bash returns exitcode 1 instead.
13150          */
13151         fullname = find_dot_file(argv[0]);
13152         argv++;
13153         args_need_save = argv[0];
13154         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13155                 int argc;
13156                 saveparam = shellparam;
13157                 shellparam.malloced = 0;
13158                 argc = 1;
13159                 while (argv[argc])
13160                         argc++;
13161                 shellparam.nparam = argc;
13162                 shellparam.p = argv;
13163         };
13164
13165         /* This aborts if file can't be opened, which is POSIXly correct.
13166          * bash returns exitcode 1 instead.
13167          */
13168         setinputfile(fullname, INPUT_PUSH_FILE);
13169         commandname = fullname;
13170         status = cmdloop(0);
13171         popfile();
13172
13173         if (args_need_save) {
13174                 freeparam(&shellparam);
13175                 shellparam = saveparam;
13176         };
13177
13178         return status;
13179 }
13180
13181 static int FAST_FUNC
13182 exitcmd(int argc UNUSED_PARAM, char **argv)
13183 {
13184         if (stoppedjobs())
13185                 return 0;
13186         if (argv[1])
13187                 exitstatus = number(argv[1]);
13188         raise_exception(EXEXIT);
13189         /* NOTREACHED */
13190 }
13191
13192 /*
13193  * Read a file containing shell functions.
13194  */
13195 static void
13196 readcmdfile(char *name)
13197 {
13198         setinputfile(name, INPUT_PUSH_FILE);
13199         cmdloop(0);
13200         popfile();
13201 }
13202
13203
13204 /* ============ find_command inplementation */
13205
13206 /*
13207  * Resolve a command name.  If you change this routine, you may have to
13208  * change the shellexec routine as well.
13209  */
13210 static void
13211 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13212 {
13213         struct tblentry *cmdp;
13214         int idx;
13215         int prev;
13216         char *fullname;
13217         struct stat statb;
13218         int e;
13219         int updatetbl;
13220         struct builtincmd *bcmd;
13221
13222         /* If name contains a slash, don't use PATH or hash table */
13223         if (strchr(name, '/') != NULL) {
13224                 entry->u.index = -1;
13225                 if (act & DO_ABS) {
13226                         while (stat(name, &statb) < 0) {
13227 #ifdef SYSV
13228                                 if (errno == EINTR)
13229                                         continue;
13230 #endif
13231                                 entry->cmdtype = CMDUNKNOWN;
13232                                 return;
13233                         }
13234                 }
13235                 entry->cmdtype = CMDNORMAL;
13236                 return;
13237         }
13238
13239 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13240
13241         updatetbl = (path == pathval());
13242         if (!updatetbl) {
13243                 act |= DO_ALTPATH;
13244                 if (strstr(path, "%builtin") != NULL)
13245                         act |= DO_ALTBLTIN;
13246         }
13247
13248         /* If name is in the table, check answer will be ok */
13249         cmdp = cmdlookup(name, 0);
13250         if (cmdp != NULL) {
13251                 int bit;
13252
13253                 switch (cmdp->cmdtype) {
13254                 default:
13255 #if DEBUG
13256                         abort();
13257 #endif
13258                 case CMDNORMAL:
13259                         bit = DO_ALTPATH;
13260                         break;
13261                 case CMDFUNCTION:
13262                         bit = DO_NOFUNC;
13263                         break;
13264                 case CMDBUILTIN:
13265                         bit = DO_ALTBLTIN;
13266                         break;
13267                 }
13268                 if (act & bit) {
13269                         updatetbl = 0;
13270                         cmdp = NULL;
13271                 } else if (cmdp->rehash == 0)
13272                         /* if not invalidated by cd, we're done */
13273                         goto success;
13274         }
13275
13276         /* If %builtin not in path, check for builtin next */
13277         bcmd = find_builtin(name);
13278         if (bcmd) {
13279                 if (IS_BUILTIN_REGULAR(bcmd))
13280                         goto builtin_success;
13281                 if (act & DO_ALTPATH) {
13282                         if (!(act & DO_ALTBLTIN))
13283                                 goto builtin_success;
13284                 } else if (builtinloc <= 0) {
13285                         goto builtin_success;
13286                 }
13287         }
13288
13289 #if ENABLE_FEATURE_SH_STANDALONE
13290         {
13291                 int applet_no = find_applet_by_name(name);
13292                 if (applet_no >= 0) {
13293                         entry->cmdtype = CMDNORMAL;
13294                         entry->u.index = -2 - applet_no;
13295                         return;
13296                 }
13297         }
13298 #endif
13299
13300         /* We have to search path. */
13301         prev = -1;              /* where to start */
13302         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13303                 if (cmdp->cmdtype == CMDBUILTIN)
13304                         prev = builtinloc;
13305                 else
13306                         prev = cmdp->param.index;
13307         }
13308
13309         e = ENOENT;
13310         idx = -1;
13311  loop:
13312         while ((fullname = path_advance(&path, name)) != NULL) {
13313                 stunalloc(fullname);
13314                 /* NB: code below will still use fullname
13315                  * despite it being "unallocated" */
13316                 idx++;
13317                 if (pathopt) {
13318                         if (prefix(pathopt, "builtin")) {
13319                                 if (bcmd)
13320                                         goto builtin_success;
13321                                 continue;
13322                         }
13323                         if ((act & DO_NOFUNC)
13324                          || !prefix(pathopt, "func")
13325                         ) {     /* ignore unimplemented options */
13326                                 continue;
13327                         }
13328                 }
13329                 /* if rehash, don't redo absolute path names */
13330                 if (fullname[0] == '/' && idx <= prev) {
13331                         if (idx < prev)
13332                                 continue;
13333                         TRACE(("searchexec \"%s\": no change\n", name));
13334                         goto success;
13335                 }
13336                 while (stat(fullname, &statb) < 0) {
13337 #ifdef SYSV
13338                         if (errno == EINTR)
13339                                 continue;
13340 #endif
13341                         if (errno != ENOENT && errno != ENOTDIR)
13342                                 e = errno;
13343                         goto loop;
13344                 }
13345                 e = EACCES;     /* if we fail, this will be the error */
13346                 if (!S_ISREG(statb.st_mode))
13347                         continue;
13348                 if (pathopt) {          /* this is a %func directory */
13349                         stalloc(strlen(fullname) + 1);
13350                         /* NB: stalloc will return space pointed by fullname
13351                          * (because we don't have any intervening allocations
13352                          * between stunalloc above and this stalloc) */
13353                         readcmdfile(fullname);
13354                         cmdp = cmdlookup(name, 0);
13355                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13356                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13357                         stunalloc(fullname);
13358                         goto success;
13359                 }
13360                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13361                 if (!updatetbl) {
13362                         entry->cmdtype = CMDNORMAL;
13363                         entry->u.index = idx;
13364                         return;
13365                 }
13366                 INT_OFF;
13367                 cmdp = cmdlookup(name, 1);
13368                 cmdp->cmdtype = CMDNORMAL;
13369                 cmdp->param.index = idx;
13370                 INT_ON;
13371                 goto success;
13372         }
13373
13374         /* We failed.  If there was an entry for this command, delete it */
13375         if (cmdp && updatetbl)
13376                 delete_cmd_entry();
13377         if (act & DO_ERR) {
13378 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13379                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13380                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13381                         char *argv[3];
13382                         argv[0] = (char*) "command_not_found_handle";
13383                         argv[1] = name;
13384                         argv[2] = NULL;
13385                         evalfun(hookp->param.func, 2, argv, 0);
13386                         entry->cmdtype = CMDUNKNOWN;
13387                         return;
13388                 }
13389 #endif
13390                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13391         }
13392         entry->cmdtype = CMDUNKNOWN;
13393         return;
13394
13395  builtin_success:
13396         if (!updatetbl) {
13397                 entry->cmdtype = CMDBUILTIN;
13398                 entry->u.cmd = bcmd;
13399                 return;
13400         }
13401         INT_OFF;
13402         cmdp = cmdlookup(name, 1);
13403         cmdp->cmdtype = CMDBUILTIN;
13404         cmdp->param.cmd = bcmd;
13405         INT_ON;
13406  success:
13407         cmdp->rehash = 0;
13408         entry->cmdtype = cmdp->cmdtype;
13409         entry->u = cmdp->param;
13410 }
13411
13412
13413 /*
13414  * The trap builtin.
13415  */
13416 static int FAST_FUNC
13417 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13418 {
13419         char *action;
13420         char **ap;
13421         int signo, exitcode;
13422
13423         nextopt(nullstr);
13424         ap = argptr;
13425         if (!*ap) {
13426                 for (signo = 0; signo < NSIG; signo++) {
13427                         char *tr = trap_ptr[signo];
13428                         if (tr) {
13429                                 /* note: bash adds "SIG", but only if invoked
13430                                  * as "bash". If called as "sh", or if set -o posix,
13431                                  * then it prints short signal names.
13432                                  * We are printing short names: */
13433                                 out1fmt("trap -- %s %s\n",
13434                                                 single_quote(tr),
13435                                                 get_signame(signo));
13436                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13437                  * In this case, we will exit very soon, no need to free(). */
13438                                 /* if (trap_ptr != trap && tp[0]) */
13439                                 /*      free(tr); */
13440                         }
13441                 }
13442                 /*
13443                 if (trap_ptr != trap) {
13444                         free(trap_ptr);
13445                         trap_ptr = trap;
13446                 }
13447                 */
13448                 return 0;
13449         }
13450
13451         /* Why the second check?
13452          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13453          * In this case, NUM is signal no, not an action.
13454          */
13455         action = NULL;
13456         if (ap[1] && !is_number(ap[0]))
13457                 action = *ap++;
13458
13459         exitcode = 0;
13460         while (*ap) {
13461                 signo = get_signum(*ap);
13462                 if (signo < 0) {
13463                         /* Mimic bash message exactly */
13464                         ash_msg("%s: invalid signal specification", *ap);
13465                         exitcode = 1;
13466                         goto next;
13467                 }
13468                 INT_OFF;
13469                 if (action) {
13470                         if (LONE_DASH(action))
13471                                 action = NULL;
13472                         else {
13473                                 if (action[0]) /* not NULL and not "" and not "-" */
13474                                         may_have_traps = 1;
13475                                 action = ckstrdup(action);
13476                         }
13477                 }
13478                 free(trap[signo]);
13479                 trap[signo] = action;
13480                 if (signo != 0)
13481                         setsignal(signo);
13482                 INT_ON;
13483  next:
13484                 ap++;
13485         }
13486         return exitcode;
13487 }
13488
13489
13490 /* ============ Builtins */
13491
13492 #if ENABLE_ASH_HELP
13493 static int FAST_FUNC
13494 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13495 {
13496         unsigned col;
13497         unsigned i;
13498
13499         out1fmt(
13500                 "Built-in commands:\n"
13501                 "------------------\n");
13502         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13503                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13504                                         builtintab[i].name + 1);
13505                 if (col > 60) {
13506                         out1fmt("\n");
13507                         col = 0;
13508                 }
13509         }
13510 # if ENABLE_FEATURE_SH_STANDALONE
13511         {
13512                 const char *a = applet_names;
13513                 while (*a) {
13514                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13515                         if (col > 60) {
13516                                 out1fmt("\n");
13517                                 col = 0;
13518                         }
13519                         while (*a++ != '\0')
13520                                 continue;
13521                 }
13522         }
13523 # endif
13524         newline_and_flush(stdout);
13525         return EXIT_SUCCESS;
13526 }
13527 #endif
13528
13529 #if MAX_HISTORY
13530 static int FAST_FUNC
13531 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13532 {
13533         show_history(line_input_state);
13534         return EXIT_SUCCESS;
13535 }
13536 #endif
13537
13538 /*
13539  * The export and readonly commands.
13540  */
13541 static int FAST_FUNC
13542 exportcmd(int argc UNUSED_PARAM, char **argv)
13543 {
13544         struct var *vp;
13545         char *name;
13546         const char *p;
13547         char **aptr;
13548         char opt;
13549         int flag;
13550         int flag_off;
13551
13552         /* "readonly" in bash accepts, but ignores -n.
13553          * We do the same: it saves a conditional in nextopt's param.
13554          */
13555         flag_off = 0;
13556         while ((opt = nextopt("np")) != '\0') {
13557                 if (opt == 'n')
13558                         flag_off = VEXPORT;
13559         }
13560         flag = VEXPORT;
13561         if (argv[0][0] == 'r') {
13562                 flag = VREADONLY;
13563                 flag_off = 0; /* readonly ignores -n */
13564         }
13565         flag_off = ~flag_off;
13566
13567         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13568         {
13569                 aptr = argptr;
13570                 name = *aptr;
13571                 if (name) {
13572                         do {
13573                                 p = strchr(name, '=');
13574                                 if (p != NULL) {
13575                                         p++;
13576                                 } else {
13577                                         vp = *findvar(hashvar(name), name);
13578                                         if (vp) {
13579                                                 vp->flags = ((vp->flags | flag) & flag_off);
13580                                                 continue;
13581                                         }
13582                                 }
13583                                 setvar(name, p, (flag & flag_off));
13584                         } while ((name = *++aptr) != NULL);
13585                         return 0;
13586                 }
13587         }
13588
13589         /* No arguments. Show the list of exported or readonly vars.
13590          * -n is ignored.
13591          */
13592         showvars(argv[0], flag, 0);
13593         return 0;
13594 }
13595
13596 /*
13597  * Delete a function if it exists.
13598  */
13599 static void
13600 unsetfunc(const char *name)
13601 {
13602         struct tblentry *cmdp;
13603
13604         cmdp = cmdlookup(name, 0);
13605         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13606                 delete_cmd_entry();
13607 }
13608
13609 /*
13610  * The unset builtin command.  We unset the function before we unset the
13611  * variable to allow a function to be unset when there is a readonly variable
13612  * with the same name.
13613  */
13614 static int FAST_FUNC
13615 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13616 {
13617         char **ap;
13618         int i;
13619         int flag = 0;
13620
13621         while ((i = nextopt("vf")) != 0) {
13622                 flag = i;
13623         }
13624
13625         for (ap = argptr; *ap; ap++) {
13626                 if (flag != 'f') {
13627                         unsetvar(*ap);
13628                         continue;
13629                 }
13630                 if (flag != 'v')
13631                         unsetfunc(*ap);
13632         }
13633         return 0;
13634 }
13635
13636 static const unsigned char timescmd_str[] ALIGN1 = {
13637         ' ',  offsetof(struct tms, tms_utime),
13638         '\n', offsetof(struct tms, tms_stime),
13639         ' ',  offsetof(struct tms, tms_cutime),
13640         '\n', offsetof(struct tms, tms_cstime),
13641         0
13642 };
13643 static int FAST_FUNC
13644 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13645 {
13646         unsigned clk_tck;
13647         const unsigned char *p;
13648         struct tms buf;
13649
13650         clk_tck = bb_clk_tck();
13651
13652         times(&buf);
13653         p = timescmd_str;
13654         do {
13655                 unsigned sec, frac;
13656                 unsigned long t;
13657                 t = *(clock_t *)(((char *) &buf) + p[1]);
13658                 sec = t / clk_tck;
13659                 frac = t % clk_tck;
13660                 out1fmt("%um%u.%03us%c",
13661                         sec / 60, sec % 60,
13662                         (frac * 1000) / clk_tck,
13663                         p[0]);
13664                 p += 2;
13665         } while (*p);
13666
13667         return 0;
13668 }
13669
13670 #if ENABLE_FEATURE_SH_MATH
13671 /*
13672  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13673  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13674  *
13675  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13676  */
13677 static int FAST_FUNC
13678 letcmd(int argc UNUSED_PARAM, char **argv)
13679 {
13680         arith_t i;
13681
13682         argv++;
13683         if (!*argv)
13684                 ash_msg_and_raise_error("expression expected");
13685         do {
13686                 i = ash_arith(*argv);
13687         } while (*++argv);
13688
13689         return !i;
13690 }
13691 #endif
13692
13693 /*
13694  * The read builtin. Options:
13695  *      -r              Do not interpret '\' specially
13696  *      -s              Turn off echo (tty only)
13697  *      -n NCHARS       Read NCHARS max
13698  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13699  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13700  *      -u FD           Read from given FD instead of fd 0
13701  *      -d DELIM        End on DELIM char, not newline
13702  * This uses unbuffered input, which may be avoidable in some cases.
13703  * TODO: bash also has:
13704  *      -a ARRAY        Read into array[0],[1],etc
13705  *      -e              Use line editing (tty only)
13706  */
13707 static int FAST_FUNC
13708 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13709 {
13710         char *opt_n = NULL;
13711         char *opt_p = NULL;
13712         char *opt_t = NULL;
13713         char *opt_u = NULL;
13714         char *opt_d = NULL; /* optimized out if !BASH */
13715         int read_flags = 0;
13716         const char *r;
13717         int i;
13718
13719         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13720                 switch (i) {
13721                 case 'p':
13722                         opt_p = optionarg;
13723                         break;
13724                 case 'n':
13725                         opt_n = optionarg;
13726                         break;
13727                 case 's':
13728                         read_flags |= BUILTIN_READ_SILENT;
13729                         break;
13730                 case 't':
13731                         opt_t = optionarg;
13732                         break;
13733                 case 'r':
13734                         read_flags |= BUILTIN_READ_RAW;
13735                         break;
13736                 case 'u':
13737                         opt_u = optionarg;
13738                         break;
13739 #if BASH_READ_D
13740                 case 'd':
13741                         opt_d = optionarg;
13742                         break;
13743 #endif
13744                 default:
13745                         break;
13746                 }
13747         }
13748
13749         /* "read -s" needs to save/restore termios, can't allow ^C
13750          * to jump out of it.
13751          */
13752  again:
13753         INT_OFF;
13754         r = shell_builtin_read(setvar0,
13755                 argptr,
13756                 bltinlookup("IFS"), /* can be NULL */
13757                 read_flags,
13758                 opt_n,
13759                 opt_p,
13760                 opt_t,
13761                 opt_u,
13762                 opt_d
13763         );
13764         INT_ON;
13765
13766         if ((uintptr_t)r == 1 && errno == EINTR) {
13767                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13768                  * Correct behavior is to not exit "read"
13769                  */
13770                 if (pending_sig == 0)
13771                         goto again;
13772         }
13773
13774         if ((uintptr_t)r > 1)
13775                 ash_msg_and_raise_error(r);
13776
13777         return (uintptr_t)r;
13778 }
13779
13780 static int FAST_FUNC
13781 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13782 {
13783         static const char permuser[3] ALIGN1 = "ogu";
13784
13785         mode_t mask;
13786         int symbolic_mode = 0;
13787
13788         while (nextopt("S") != '\0') {
13789                 symbolic_mode = 1;
13790         }
13791
13792         INT_OFF;
13793         mask = umask(0);
13794         umask(mask);
13795         INT_ON;
13796
13797         if (*argptr == NULL) {
13798                 if (symbolic_mode) {
13799                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13800                         char *p = buf;
13801                         int i;
13802
13803                         i = 2;
13804                         for (;;) {
13805                                 *p++ = ',';
13806                                 *p++ = permuser[i];
13807                                 *p++ = '=';
13808                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13809                                 if (!(mask & 0400)) *p++ = 'r';
13810                                 if (!(mask & 0200)) *p++ = 'w';
13811                                 if (!(mask & 0100)) *p++ = 'x';
13812                                 mask <<= 3;
13813                                 if (--i < 0)
13814                                         break;
13815                         }
13816                         *p = '\0';
13817                         puts(buf + 1);
13818                 } else {
13819                         out1fmt("%04o\n", mask);
13820                 }
13821         } else {
13822                 char *modestr = *argptr;
13823                 /* numeric umasks are taken as-is */
13824                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13825                 if (!isdigit(modestr[0]))
13826                         mask ^= 0777;
13827                 mask = bb_parse_mode(modestr, mask);
13828                 if ((unsigned)mask > 0777) {
13829                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13830                 }
13831                 if (!isdigit(modestr[0]))
13832                         mask ^= 0777;
13833                 umask(mask);
13834         }
13835         return 0;
13836 }
13837
13838 static int FAST_FUNC
13839 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13840 {
13841         return shell_builtin_ulimit(argv);
13842 }
13843
13844 /* ============ main() and helpers */
13845
13846 /*
13847  * Called to exit the shell.
13848  */
13849 static void
13850 exitshell(void)
13851 {
13852         struct jmploc loc;
13853         char *p;
13854         int status;
13855
13856 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13857         save_history(line_input_state);
13858 #endif
13859         status = exitstatus;
13860         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13861         if (setjmp(loc.loc)) {
13862                 if (exception_type == EXEXIT)
13863                         status = exitstatus;
13864                 goto out;
13865         }
13866         exception_handler = &loc;
13867         p = trap[0];
13868         if (p) {
13869                 trap[0] = NULL;
13870                 evalskip = 0;
13871                 evalstring(p, 0);
13872                 /*free(p); - we'll exit soon */
13873         }
13874  out:
13875         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13876          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13877          */
13878         setjobctl(0);
13879         flush_stdout_stderr();
13880         _exit(status);
13881         /* NOTREACHED */
13882 }
13883
13884 /* Don't inline: conserve stack of caller from having our locals too */
13885 static NOINLINE void
13886 init(void)
13887 {
13888         /* we will never free this */
13889         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13890         basepf.linno = 1;
13891
13892         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13893         setsignal(SIGCHLD);
13894
13895         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13896          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13897          */
13898         signal(SIGHUP, SIG_DFL);
13899
13900         {
13901                 char **envp;
13902                 const char *p;
13903
13904                 initvar();
13905                 for (envp = environ; envp && *envp; envp++) {
13906 /* Used to have
13907  *                      p = endofname(*envp);
13908  *                      if (p != *envp && *p == '=') {
13909  * here to weed out badly-named variables, but this breaks
13910  * scenarios where people do want them passed to children:
13911  * import os
13912  * os.environ["test-test"]="test"
13913  * if os.fork() == 0:
13914  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13915  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13916  */
13917                         if (strchr(*envp, '=')) {
13918                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13919                         }
13920                 }
13921
13922                 setvareq((char*)defoptindvar, VTEXTFIXED);
13923
13924                 setvar0("PPID", utoa(getppid()));
13925 #if BASH_SHLVL_VAR
13926                 p = lookupvar("SHLVL");
13927                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13928 #endif
13929 #if BASH_HOSTNAME_VAR
13930                 if (!lookupvar("HOSTNAME")) {
13931                         struct utsname uts;
13932                         uname(&uts);
13933                         setvar0("HOSTNAME", uts.nodename);
13934                 }
13935 #endif
13936                 p = lookupvar("PWD");
13937                 if (p) {
13938                         struct stat st1, st2;
13939                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13940                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13941                         ) {
13942                                 p = NULL;
13943                         }
13944                 }
13945                 setpwd(p, 0);
13946         }
13947 }
13948
13949
13950 //usage:#define ash_trivial_usage
13951 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13952 //usage:#define ash_full_usage "\n\n"
13953 //usage:        "Unix shell interpreter"
13954
13955 /*
13956  * Process the shell command line arguments.
13957  */
13958 static int
13959 procargs(char **argv)
13960 {
13961         int i;
13962         const char *xminusc;
13963         char **xargv;
13964         int login_sh;
13965
13966         xargv = argv;
13967         login_sh = xargv[0] && xargv[0][0] == '-';
13968         arg0 = xargv[0];
13969         /* if (xargv[0]) - mmm, this is always true! */
13970                 xargv++;
13971         for (i = 0; i < NOPTS; i++)
13972                 optlist[i] = 2;
13973         argptr = xargv;
13974         if (options(/*cmdline:*/ 1, &login_sh)) {
13975                 /* it already printed err message */
13976                 raise_exception(EXERROR);
13977         }
13978         xargv = argptr;
13979         xminusc = minusc;
13980         if (*xargv == NULL) {
13981                 if (xminusc)
13982                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13983                 sflag = 1;
13984         }
13985         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13986                 iflag = 1;
13987         if (mflag == 2)
13988                 mflag = iflag;
13989         for (i = 0; i < NOPTS; i++)
13990                 if (optlist[i] == 2)
13991                         optlist[i] = 0;
13992 #if DEBUG == 2
13993         debug = 1;
13994 #endif
13995         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13996         if (xminusc) {
13997                 minusc = *xargv++;
13998                 if (*xargv)
13999                         goto setarg0;
14000         } else if (!sflag) {
14001                 setinputfile(*xargv, 0);
14002  setarg0:
14003                 arg0 = *xargv++;
14004                 commandname = arg0;
14005         }
14006
14007         shellparam.p = xargv;
14008 #if ENABLE_ASH_GETOPTS
14009         shellparam.optind = 1;
14010         shellparam.optoff = -1;
14011 #endif
14012         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14013         while (*xargv) {
14014                 shellparam.nparam++;
14015                 xargv++;
14016         }
14017         optschanged();
14018
14019         return login_sh;
14020 }
14021
14022 /*
14023  * Read /etc/profile, ~/.profile, $ENV.
14024  */
14025 static void
14026 read_profile(const char *name)
14027 {
14028         name = expandstr(name, DQSYNTAX);
14029         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14030                 return;
14031         cmdloop(0);
14032         popfile();
14033 }
14034
14035 /*
14036  * This routine is called when an error or an interrupt occurs in an
14037  * interactive shell and control is returned to the main command loop.
14038  * (In dash, this function is auto-generated by build machinery).
14039  */
14040 static void
14041 reset(void)
14042 {
14043         /* from eval.c: */
14044         evalskip = 0;
14045         loopnest = 0;
14046
14047         /* from expand.c: */
14048         ifsfree();
14049
14050         /* from input.c: */
14051         g_parsefile->left_in_buffer = 0;
14052         g_parsefile->left_in_line = 0;      /* clear input buffer */
14053         popallfiles();
14054
14055         /* from redir.c: */
14056         unwindredir(NULL);
14057
14058         /* from var.c: */
14059         unwindlocalvars(NULL);
14060 }
14061
14062 #if PROFILE
14063 static short profile_buf[16384];
14064 extern int etext();
14065 #endif
14066
14067 /*
14068  * Main routine.  We initialize things, parse the arguments, execute
14069  * profiles if we're a login shell, and then call cmdloop to execute
14070  * commands.  The setjmp call sets up the location to jump to when an
14071  * exception occurs.  When an exception occurs the variable "state"
14072  * is used to figure out how far we had gotten.
14073  */
14074 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14075 int ash_main(int argc UNUSED_PARAM, char **argv)
14076 {
14077         volatile smallint state;
14078         struct jmploc jmploc;
14079         struct stackmark smark;
14080         int login_sh;
14081
14082         /* Initialize global data */
14083         INIT_G_misc();
14084         INIT_G_memstack();
14085         INIT_G_var();
14086 #if ENABLE_ASH_ALIAS
14087         INIT_G_alias();
14088 #endif
14089         INIT_G_cmdtable();
14090
14091 #if PROFILE
14092         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14093 #endif
14094
14095 #if ENABLE_FEATURE_EDITING
14096         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14097 #endif
14098         state = 0;
14099         if (setjmp(jmploc.loc)) {
14100                 smallint e;
14101                 smallint s;
14102
14103                 reset();
14104
14105                 e = exception_type;
14106                 s = state;
14107                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14108                         exitshell();
14109                 }
14110                 if (e == EXINT) {
14111                         newline_and_flush(stderr);
14112                 }
14113
14114                 popstackmark(&smark);
14115                 FORCE_INT_ON; /* enable interrupts */
14116                 if (s == 1)
14117                         goto state1;
14118                 if (s == 2)
14119                         goto state2;
14120                 if (s == 3)
14121                         goto state3;
14122                 goto state4;
14123         }
14124         exception_handler = &jmploc;
14125         rootpid = getpid();
14126
14127         init();
14128         setstackmark(&smark);
14129         login_sh = procargs(argv);
14130 #if DEBUG
14131         TRACE(("Shell args: "));
14132         trace_puts_args(argv);
14133 #endif
14134
14135         if (login_sh) {
14136                 const char *hp;
14137
14138                 state = 1;
14139                 read_profile("/etc/profile");
14140  state1:
14141                 state = 2;
14142                 hp = lookupvar("HOME");
14143                 if (hp)
14144                         read_profile("$HOME/.profile");
14145         }
14146  state2:
14147         state = 3;
14148         if (
14149 #ifndef linux
14150          getuid() == geteuid() && getgid() == getegid() &&
14151 #endif
14152          iflag
14153         ) {
14154                 const char *shinit = lookupvar("ENV");
14155                 if (shinit != NULL && *shinit != '\0')
14156                         read_profile(shinit);
14157         }
14158         popstackmark(&smark);
14159  state3:
14160         state = 4;
14161         if (minusc) {
14162                 /* evalstring pushes parsefile stack.
14163                  * Ensure we don't falsely claim that 0 (stdin)
14164                  * is one of stacked source fds.
14165                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14166                 // if (!sflag) g_parsefile->pf_fd = -1;
14167                 // ^^ not necessary since now we special-case fd 0
14168                 // in save_fd_on_redirect()
14169                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14170         }
14171
14172         if (sflag || minusc == NULL) {
14173 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14174                 if (iflag) {
14175                         const char *hp = lookupvar("HISTFILE");
14176                         if (!hp) {
14177                                 hp = lookupvar("HOME");
14178                                 if (hp) {
14179                                         INT_OFF;
14180                                         hp = concat_path_file(hp, ".ash_history");
14181                                         setvar0("HISTFILE", hp);
14182                                         free((char*)hp);
14183                                         INT_ON;
14184                                         hp = lookupvar("HISTFILE");
14185                                 }
14186                         }
14187                         if (hp)
14188                                 line_input_state->hist_file = hp;
14189 # if ENABLE_FEATURE_SH_HISTFILESIZE
14190                         hp = lookupvar("HISTFILESIZE");
14191                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14192 # endif
14193                 }
14194 #endif
14195  state4: /* XXX ??? - why isn't this before the "if" statement */
14196                 cmdloop(1);
14197         }
14198 #if PROFILE
14199         monitor(0);
14200 #endif
14201 #ifdef GPROF
14202         {
14203                 extern void _mcleanup(void);
14204                 _mcleanup();
14205         }
14206 #endif
14207         TRACE(("End of main reached\n"));
14208         exitshell();
14209         /* NOTREACHED */
14210 }
14211
14212
14213 /*-
14214  * Copyright (c) 1989, 1991, 1993, 1994
14215  *      The Regents of the University of California.  All rights reserved.
14216  *
14217  * This code is derived from software contributed to Berkeley by
14218  * Kenneth Almquist.
14219  *
14220  * Redistribution and use in source and binary forms, with or without
14221  * modification, are permitted provided that the following conditions
14222  * are met:
14223  * 1. Redistributions of source code must retain the above copyright
14224  *    notice, this list of conditions and the following disclaimer.
14225  * 2. Redistributions in binary form must reproduce the above copyright
14226  *    notice, this list of conditions and the following disclaimer in the
14227  *    documentation and/or other materials provided with the distribution.
14228  * 3. Neither the name of the University nor the names of its contributors
14229  *    may be used to endorse or promote products derived from this software
14230  *    without specific prior written permission.
14231  *
14232  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14233  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14234  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14235  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14236  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14237  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14238  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14239  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14240  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14241  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14242  * SUCH DAMAGE.
14243  */