85690e555d1d387ac93049a14c078a78f4cdcb7e
[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 PIPE_BUF
262 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
263 #endif
264
265 #if !BB_MMU
266 # error "Do not even bother, ash will not run on NOMMU machine"
267 #endif
268
269 /* We use a trick to have more optimized code (fewer pointer reloads):
270  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
271  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
272  * This way, compiler in ash.c knows the pointer can not change.
273  *
274  * However, this may break on weird arches or toolchains. In this case,
275  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
276  * this optimization.
277  */
278 #ifndef BB_GLOBAL_CONST
279 # define BB_GLOBAL_CONST const
280 #endif
281
282
283 /* ============ Hash table sizes. Configurable. */
284
285 #define VTABSIZE 39
286 #define ATABSIZE 39
287 #define CMDTABLESIZE 31         /* should be prime */
288
289
290 /* ============ Shell options */
291
292 static const char *const optletters_optnames[] = {
293         "e"   "errexit",
294         "f"   "noglob",
295         "I"   "ignoreeof",
296         "i"   "interactive",
297         "m"   "monitor",
298         "n"   "noexec",
299         "s"   "stdin",
300         "x"   "xtrace",
301         "v"   "verbose",
302         "C"   "noclobber",
303         "a"   "allexport",
304         "b"   "notify",
305         "u"   "nounset",
306         "\0"  "vi"
307 #if BASH_PIPEFAIL
308         ,"\0"  "pipefail"
309 #endif
310 #if DEBUG
311         ,"\0"  "nolog"
312         ,"\0"  "debug"
313 #endif
314 };
315
316 #define optletters(n)  optletters_optnames[n][0]
317 #define optnames(n)   (optletters_optnames[n] + 1)
318
319 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
320
321
322 /* ============ Misc data */
323
324 #define msg_illnum "Illegal number: %s"
325
326 /*
327  * We enclose jmp_buf in a structure so that we can declare pointers to
328  * jump locations.  The global variable handler contains the location to
329  * jump to when an exception occurs, and the global variable exception_type
330  * contains a code identifying the exception.  To implement nested
331  * exception handlers, the user should save the value of handler on entry
332  * to an inner scope, set handler to point to a jmploc structure for the
333  * inner scope, and restore handler on exit from the scope.
334  */
335 struct jmploc {
336         jmp_buf loc;
337 };
338
339 struct globals_misc {
340         uint8_t exitstatus;     /* exit status of last command */
341         uint8_t back_exitstatus;/* exit status of backquoted command */
342         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
343         int rootpid;            /* pid of main shell */
344         /* shell level: 0 for the main shell, 1 for its children, and so on */
345         int shlvl;
346 #define rootshell (!shlvl)
347         int errlinno;
348
349         char *minusc;  /* argument to -c option */
350
351         char *curdir; // = nullstr;     /* current working directory */
352         char *physdir; // = nullstr;    /* physical working directory */
353
354         char *arg0; /* value of $0 */
355
356         struct jmploc *exception_handler;
357
358         volatile int suppress_int; /* counter */
359         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
360         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
361         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
362         smallint exception_type; /* kind of exception (0..5) */
363         /* exceptions */
364 #define EXINT 0         /* SIGINT received */
365 #define EXERROR 1       /* a generic error */
366 #define EXEXIT 4        /* exit the shell */
367
368         char nullstr[1];        /* zero length string */
369
370         char optlist[NOPTS];
371 #define eflag optlist[0]
372 #define fflag optlist[1]
373 #define Iflag optlist[2]
374 #define iflag optlist[3]
375 #define mflag optlist[4]
376 #define nflag optlist[5]
377 #define sflag optlist[6]
378 #define xflag optlist[7]
379 #define vflag optlist[8]
380 #define Cflag optlist[9]
381 #define aflag optlist[10]
382 #define bflag optlist[11]
383 #define uflag optlist[12]
384 #define viflag optlist[13]
385 #if BASH_PIPEFAIL
386 # define pipefail optlist[14]
387 #else
388 # define pipefail 0
389 #endif
390 #if DEBUG
391 # define nolog optlist[14 + BASH_PIPEFAIL]
392 # define debug optlist[15 + BASH_PIPEFAIL]
393 #endif
394
395         /* trap handler commands */
396         /*
397          * Sigmode records the current value of the signal handlers for the various
398          * modes.  A value of zero means that the current handler is not known.
399          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
400          */
401         char sigmode[NSIG - 1];
402 #define S_DFL      1            /* default signal handling (SIG_DFL) */
403 #define S_CATCH    2            /* signal is caught */
404 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
405 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
406
407         /* indicates specified signal received */
408         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
409         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
410         char *trap[NSIG];
411         char **trap_ptr;        /* used only by "trap hack" */
412
413         /* Rarely referenced stuff */
414 #if ENABLE_ASH_RANDOM_SUPPORT
415         random_t random_gen;
416 #endif
417         pid_t backgndpid;        /* pid of last background process */
418 };
419 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
420 #define G_misc (*ash_ptr_to_globals_misc)
421 #define exitstatus        (G_misc.exitstatus )
422 #define back_exitstatus   (G_misc.back_exitstatus )
423 #define job_warning       (G_misc.job_warning)
424 #define rootpid     (G_misc.rootpid    )
425 #define shlvl       (G_misc.shlvl      )
426 #define errlinno    (G_misc.errlinno   )
427 #define minusc      (G_misc.minusc     )
428 #define curdir      (G_misc.curdir     )
429 #define physdir     (G_misc.physdir    )
430 #define arg0        (G_misc.arg0       )
431 #define exception_handler (G_misc.exception_handler)
432 #define exception_type    (G_misc.exception_type   )
433 #define suppress_int      (G_misc.suppress_int     )
434 #define pending_int       (G_misc.pending_int      )
435 #define got_sigchld       (G_misc.got_sigchld      )
436 #define pending_sig       (G_misc.pending_sig      )
437 #define nullstr     (G_misc.nullstr    )
438 #define optlist     (G_misc.optlist    )
439 #define sigmode     (G_misc.sigmode    )
440 #define gotsig      (G_misc.gotsig     )
441 #define may_have_traps    (G_misc.may_have_traps   )
442 #define trap        (G_misc.trap       )
443 #define trap_ptr    (G_misc.trap_ptr   )
444 #define random_gen  (G_misc.random_gen )
445 #define backgndpid  (G_misc.backgndpid )
446 #define INIT_G_misc() do { \
447         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
448         barrier(); \
449         curdir = nullstr; \
450         physdir = nullstr; \
451         trap_ptr = trap; \
452 } while (0)
453
454
455 /* ============ DEBUG */
456 #if DEBUG
457 static void trace_printf(const char *fmt, ...);
458 static void trace_vprintf(const char *fmt, va_list va);
459 # define TRACE(param)    trace_printf param
460 # define TRACEV(param)   trace_vprintf param
461 # define close(fd) do { \
462         int dfd = (fd); \
463         if (close(dfd) < 0) \
464                 bb_error_msg("bug on %d: closing %d(0x%x)", \
465                         __LINE__, dfd, dfd); \
466 } while (0)
467 #else
468 # define TRACE(param)
469 # define TRACEV(param)
470 #endif
471
472
473 /* ============ Utility functions */
474 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
475 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
476
477 static int
478 isdigit_str9(const char *str)
479 {
480         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
481         while (--maxlen && isdigit(*str))
482                 str++;
483         return (*str == '\0');
484 }
485
486 static const char *
487 var_end(const char *var)
488 {
489         while (*var)
490                 if (*var++ == '=')
491                         break;
492         return var;
493 }
494
495
496 /* ============ Interrupts / exceptions */
497
498 static void exitshell(void) NORETURN;
499
500 /*
501  * These macros allow the user to suspend the handling of interrupt signals
502  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
503  * much more efficient and portable.  (But hacking the kernel is so much
504  * more fun than worrying about efficiency and portability. :-))
505  */
506 #if DEBUG_INTONOFF
507 # define INT_OFF do { \
508         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
509         suppress_int++; \
510         barrier(); \
511 } while (0)
512 #else
513 # define INT_OFF do { \
514         suppress_int++; \
515         barrier(); \
516 } while (0)
517 #endif
518
519 /*
520  * Called to raise an exception.  Since C doesn't include exceptions, we
521  * just do a longjmp to the exception handler.  The type of exception is
522  * stored in the global variable "exception_type".
523  */
524 static void raise_exception(int) NORETURN;
525 static void
526 raise_exception(int e)
527 {
528 #if DEBUG
529         if (exception_handler == NULL)
530                 abort();
531 #endif
532         INT_OFF;
533         exception_type = e;
534         longjmp(exception_handler->loc, 1);
535 }
536 #if DEBUG
537 #define raise_exception(e) do { \
538         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
539         raise_exception(e); \
540 } while (0)
541 #endif
542
543 /*
544  * Called when a SIGINT is received.  (If the user specifies
545  * that SIGINT is to be trapped or ignored using the trap builtin, then
546  * this routine is not called.)  Suppressint is nonzero when interrupts
547  * are held using the INT_OFF macro.  (The test for iflag is just
548  * defensive programming.)
549  */
550 static void raise_interrupt(void) NORETURN;
551 static void
552 raise_interrupt(void)
553 {
554         pending_int = 0;
555         /* Signal is not automatically unmasked after it is raised,
556          * do it ourself - unmask all signals */
557         sigprocmask_allsigs(SIG_UNBLOCK);
558         /* pending_sig = 0; - now done in signal_handler() */
559
560         if (!(rootshell && iflag)) {
561                 /* Kill ourself with SIGINT */
562                 signal(SIGINT, SIG_DFL);
563                 raise(SIGINT);
564         }
565         /* bash: ^C even on empty command line sets $? */
566         exitstatus = SIGINT + 128;
567         raise_exception(EXINT);
568         /* NOTREACHED */
569 }
570 #if DEBUG
571 #define raise_interrupt() do { \
572         TRACE(("raising interrupt on line %d\n", __LINE__)); \
573         raise_interrupt(); \
574 } while (0)
575 #endif
576
577 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
578 int_on(void)
579 {
580         barrier();
581         if (--suppress_int == 0 && pending_int) {
582                 raise_interrupt();
583         }
584 }
585 #if DEBUG_INTONOFF
586 # define INT_ON do { \
587         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
588         int_on(); \
589 } while (0)
590 #else
591 # define INT_ON int_on()
592 #endif
593 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
594 force_int_on(void)
595 {
596         barrier();
597         suppress_int = 0;
598         if (pending_int)
599                 raise_interrupt();
600 }
601 #define FORCE_INT_ON force_int_on()
602
603 #define SAVE_INT(v) ((v) = suppress_int)
604
605 #define RESTORE_INT(v) do { \
606         barrier(); \
607         suppress_int = (v); \
608         if (suppress_int == 0 && pending_int) \
609                 raise_interrupt(); \
610 } while (0)
611
612
613 /* ============ Stdout/stderr output */
614
615 static void
616 outstr(const char *p, FILE *file)
617 {
618         INT_OFF;
619         fputs(p, file);
620         INT_ON;
621 }
622
623 static void
624 flush_stdout_stderr(void)
625 {
626         INT_OFF;
627         fflush_all();
628         INT_ON;
629 }
630
631 /* Was called outcslow(c,FILE*), but c was always '\n' */
632 static void
633 newline_and_flush(FILE *dest)
634 {
635         INT_OFF;
636         putc('\n', dest);
637         fflush(dest);
638         INT_ON;
639 }
640
641 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
642 static int
643 out1fmt(const char *fmt, ...)
644 {
645         va_list ap;
646         int r;
647
648         INT_OFF;
649         va_start(ap, fmt);
650         r = vprintf(fmt, ap);
651         va_end(ap);
652         INT_ON;
653         return r;
654 }
655
656 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
657 static int
658 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
659 {
660         va_list ap;
661         int ret;
662
663         INT_OFF;
664         va_start(ap, fmt);
665         ret = vsnprintf(outbuf, length, fmt, ap);
666         va_end(ap);
667         INT_ON;
668         return ret;
669 }
670
671 static void
672 out1str(const char *p)
673 {
674         outstr(p, stdout);
675 }
676
677 static void
678 out2str(const char *p)
679 {
680         outstr(p, stderr);
681         flush_stdout_stderr();
682 }
683
684
685 /* ============ Parser structures */
686
687 /* control characters in argument strings */
688 #define CTL_FIRST CTLESC
689 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
690 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
691 #define CTLENDVAR    ((unsigned char)'\203')
692 #define CTLBACKQ     ((unsigned char)'\204')
693 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
694 #define CTLENDARI    ((unsigned char)'\207')
695 #define CTLQUOTEMARK ((unsigned char)'\210')
696 #define CTL_LAST CTLQUOTEMARK
697
698 /* variable substitution byte (follows CTLVAR) */
699 #define VSTYPE  0x0f            /* type of variable substitution */
700 #define VSNUL   0x10            /* colon--treat the empty string as unset */
701
702 /* values of VSTYPE field */
703 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
704 #define VSMINUS         0x2     /* ${var-text} */
705 #define VSPLUS          0x3     /* ${var+text} */
706 #define VSQUESTION      0x4     /* ${var?message} */
707 #define VSASSIGN        0x5     /* ${var=text} */
708 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
709 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
710 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
711 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
712 #define VSLENGTH        0xa     /* ${#var} */
713 #if BASH_SUBSTR
714 #define VSSUBSTR        0xc     /* ${var:position:length} */
715 #endif
716 #if BASH_PATTERN_SUBST
717 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
718 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
719 #endif
720
721 static const char dolatstr[] ALIGN1 = {
722         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
723 };
724 #define DOLATSTRLEN 6
725
726 #define NCMD      0
727 #define NPIPE     1
728 #define NREDIR    2
729 #define NBACKGND  3
730 #define NSUBSHELL 4
731 #define NAND      5
732 #define NOR       6
733 #define NSEMI     7
734 #define NIF       8
735 #define NWHILE    9
736 #define NUNTIL   10
737 #define NFOR     11
738 #define NCASE    12
739 #define NCLIST   13
740 #define NDEFUN   14
741 #define NARG     15
742 #define NTO      16
743 #if BASH_REDIR_OUTPUT
744 #define NTO2     17
745 #endif
746 #define NCLOBBER 18
747 #define NFROM    19
748 #define NFROMTO  20
749 #define NAPPEND  21
750 #define NTOFD    22
751 #define NFROMFD  23
752 #define NHERE    24
753 #define NXHERE   25
754 #define NNOT     26
755 #define N_NUMBER 27
756
757 union node;
758
759 struct ncmd {
760         smallint type; /* Nxxxx */
761         int linno;
762         union node *assign;
763         union node *args;
764         union node *redirect;
765 };
766
767 struct npipe {
768         smallint type;
769         smallint pipe_backgnd;
770         struct nodelist *cmdlist;
771 };
772
773 struct nredir {
774         smallint type;
775         int linno;
776         union node *n;
777         union node *redirect;
778 };
779
780 struct nbinary {
781         smallint type;
782         union node *ch1;
783         union node *ch2;
784 };
785
786 struct nif {
787         smallint type;
788         union node *test;
789         union node *ifpart;
790         union node *elsepart;
791 };
792
793 struct nfor {
794         smallint type;
795         int linno;
796         union node *args;
797         union node *body;
798         char *var;
799 };
800
801 struct ncase {
802         smallint type;
803         int linno;
804         union node *expr;
805         union node *cases;
806 };
807
808 struct nclist {
809         smallint type;
810         union node *next;
811         union node *pattern;
812         union node *body;
813 };
814
815 struct ndefun {
816         smallint type;
817         int linno;
818         char *text;
819         union node *body;
820 };
821
822 struct narg {
823         smallint type;
824         union node *next;
825         char *text;
826         struct nodelist *backquote;
827 };
828
829 /* nfile and ndup layout must match!
830  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
831  * that it is actually NTO2 (>&file), and change its type.
832  */
833 struct nfile {
834         smallint type;
835         union node *next;
836         int fd;
837         int _unused_dupfd;
838         union node *fname;
839         char *expfname;
840 };
841
842 struct ndup {
843         smallint type;
844         union node *next;
845         int fd;
846         int dupfd;
847         union node *vname;
848         char *_unused_expfname;
849 };
850
851 struct nhere {
852         smallint type;
853         union node *next;
854         int fd;
855         union node *doc;
856 };
857
858 struct nnot {
859         smallint type;
860         union node *com;
861 };
862
863 union node {
864         smallint type;
865         struct ncmd ncmd;
866         struct npipe npipe;
867         struct nredir nredir;
868         struct nbinary nbinary;
869         struct nif nif;
870         struct nfor nfor;
871         struct ncase ncase;
872         struct nclist nclist;
873         struct ndefun ndefun;
874         struct narg narg;
875         struct nfile nfile;
876         struct ndup ndup;
877         struct nhere nhere;
878         struct nnot nnot;
879 };
880
881 /*
882  * NODE_EOF is returned by parsecmd when it encounters an end of file.
883  * It must be distinct from NULL.
884  */
885 #define NODE_EOF ((union node *) -1L)
886
887 struct nodelist {
888         struct nodelist *next;
889         union node *n;
890 };
891
892 struct funcnode {
893         int count;
894         union node n;
895 };
896
897 /*
898  * Free a parse tree.
899  */
900 static void
901 freefunc(struct funcnode *f)
902 {
903         if (f && --f->count < 0)
904                 free(f);
905 }
906
907
908 /* ============ Debugging output */
909
910 #if DEBUG
911
912 static FILE *tracefile;
913
914 static void
915 trace_printf(const char *fmt, ...)
916 {
917         va_list va;
918
919         if (debug != 1)
920                 return;
921         if (DEBUG_TIME)
922                 fprintf(tracefile, "%u ", (int) time(NULL));
923         if (DEBUG_PID)
924                 fprintf(tracefile, "[%u] ", (int) getpid());
925         if (DEBUG_SIG)
926                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
927         va_start(va, fmt);
928         vfprintf(tracefile, fmt, va);
929         va_end(va);
930 }
931
932 static void
933 trace_vprintf(const char *fmt, va_list va)
934 {
935         if (debug != 1)
936                 return;
937         vfprintf(tracefile, fmt, va);
938         fprintf(tracefile, "\n");
939 }
940
941 static void
942 trace_puts(const char *s)
943 {
944         if (debug != 1)
945                 return;
946         fputs(s, tracefile);
947 }
948
949 static void
950 trace_puts_quoted(char *s)
951 {
952         char *p;
953         char c;
954
955         if (debug != 1)
956                 return;
957         putc('"', tracefile);
958         for (p = s; *p; p++) {
959                 switch ((unsigned char)*p) {
960                 case '\n': c = 'n'; goto backslash;
961                 case '\t': c = 't'; goto backslash;
962                 case '\r': c = 'r'; goto backslash;
963                 case '\"': c = '\"'; goto backslash;
964                 case '\\': c = '\\'; goto backslash;
965                 case CTLESC: c = 'e'; goto backslash;
966                 case CTLVAR: c = 'v'; goto backslash;
967                 case CTLBACKQ: c = 'q'; goto backslash;
968  backslash:
969                         putc('\\', tracefile);
970                         putc(c, tracefile);
971                         break;
972                 default:
973                         if (*p >= ' ' && *p <= '~')
974                                 putc(*p, tracefile);
975                         else {
976                                 putc('\\', tracefile);
977                                 putc((*p >> 6) & 03, tracefile);
978                                 putc((*p >> 3) & 07, tracefile);
979                                 putc(*p & 07, tracefile);
980                         }
981                         break;
982                 }
983         }
984         putc('"', tracefile);
985 }
986
987 static void
988 trace_puts_args(char **ap)
989 {
990         if (debug != 1)
991                 return;
992         if (!*ap)
993                 return;
994         while (1) {
995                 trace_puts_quoted(*ap);
996                 if (!*++ap) {
997                         putc('\n', tracefile);
998                         break;
999                 }
1000                 putc(' ', tracefile);
1001         }
1002 }
1003
1004 static void
1005 opentrace(void)
1006 {
1007         char s[100];
1008 #ifdef O_APPEND
1009         int flags;
1010 #endif
1011
1012         if (debug != 1) {
1013                 if (tracefile)
1014                         fflush(tracefile);
1015                 /* leave open because libedit might be using it */
1016                 return;
1017         }
1018         strcpy(s, "./trace");
1019         if (tracefile) {
1020                 if (!freopen(s, "a", tracefile)) {
1021                         fprintf(stderr, "Can't re-open %s\n", s);
1022                         debug = 0;
1023                         return;
1024                 }
1025         } else {
1026                 tracefile = fopen(s, "a");
1027                 if (tracefile == NULL) {
1028                         fprintf(stderr, "Can't open %s\n", s);
1029                         debug = 0;
1030                         return;
1031                 }
1032         }
1033 #ifdef O_APPEND
1034         flags = fcntl(fileno(tracefile), F_GETFL);
1035         if (flags >= 0)
1036                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1037 #endif
1038         setlinebuf(tracefile);
1039         fputs("\nTracing started.\n", tracefile);
1040 }
1041
1042 static void
1043 indent(int amount, char *pfx, FILE *fp)
1044 {
1045         int i;
1046
1047         for (i = 0; i < amount; i++) {
1048                 if (pfx && i == amount - 1)
1049                         fputs(pfx, fp);
1050                 putc('\t', fp);
1051         }
1052 }
1053
1054 /* little circular references here... */
1055 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1056
1057 static void
1058 sharg(union node *arg, FILE *fp)
1059 {
1060         char *p;
1061         struct nodelist *bqlist;
1062         unsigned char subtype;
1063
1064         if (arg->type != NARG) {
1065                 out1fmt("<node type %d>\n", arg->type);
1066                 abort();
1067         }
1068         bqlist = arg->narg.backquote;
1069         for (p = arg->narg.text; *p; p++) {
1070                 switch ((unsigned char)*p) {
1071                 case CTLESC:
1072                         p++;
1073                         putc(*p, fp);
1074                         break;
1075                 case CTLVAR:
1076                         putc('$', fp);
1077                         putc('{', fp);
1078                         subtype = *++p;
1079                         if (subtype == VSLENGTH)
1080                                 putc('#', fp);
1081
1082                         while (*p != '=') {
1083                                 putc(*p, fp);
1084                                 p++;
1085                         }
1086
1087                         if (subtype & VSNUL)
1088                                 putc(':', fp);
1089
1090                         switch (subtype & VSTYPE) {
1091                         case VSNORMAL:
1092                                 putc('}', fp);
1093                                 break;
1094                         case VSMINUS:
1095                                 putc('-', fp);
1096                                 break;
1097                         case VSPLUS:
1098                                 putc('+', fp);
1099                                 break;
1100                         case VSQUESTION:
1101                                 putc('?', fp);
1102                                 break;
1103                         case VSASSIGN:
1104                                 putc('=', fp);
1105                                 break;
1106                         case VSTRIMLEFT:
1107                                 putc('#', fp);
1108                                 break;
1109                         case VSTRIMLEFTMAX:
1110                                 putc('#', fp);
1111                                 putc('#', fp);
1112                                 break;
1113                         case VSTRIMRIGHT:
1114                                 putc('%', fp);
1115                                 break;
1116                         case VSTRIMRIGHTMAX:
1117                                 putc('%', fp);
1118                                 putc('%', fp);
1119                                 break;
1120                         case VSLENGTH:
1121                                 break;
1122                         default:
1123                                 out1fmt("<subtype %d>", subtype);
1124                         }
1125                         break;
1126                 case CTLENDVAR:
1127                         putc('}', fp);
1128                         break;
1129                 case CTLBACKQ:
1130                         putc('$', fp);
1131                         putc('(', fp);
1132                         shtree(bqlist->n, -1, NULL, fp);
1133                         putc(')', fp);
1134                         break;
1135                 default:
1136                         putc(*p, fp);
1137                         break;
1138                 }
1139         }
1140 }
1141
1142 static void
1143 shcmd(union node *cmd, FILE *fp)
1144 {
1145         union node *np;
1146         int first;
1147         const char *s;
1148         int dftfd;
1149
1150         first = 1;
1151         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1152                 if (!first)
1153                         putc(' ', fp);
1154                 sharg(np, fp);
1155                 first = 0;
1156         }
1157         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1158                 if (!first)
1159                         putc(' ', fp);
1160                 dftfd = 0;
1161                 switch (np->nfile.type) {
1162                 case NTO:      s = ">>"+1; dftfd = 1; break;
1163                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1164                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1165 #if BASH_REDIR_OUTPUT
1166                 case NTO2:
1167 #endif
1168                 case NTOFD:    s = ">&"; dftfd = 1; break;
1169                 case NFROM:    s = "<"; break;
1170                 case NFROMFD:  s = "<&"; break;
1171                 case NFROMTO:  s = "<>"; break;
1172                 default:       s = "*error*"; break;
1173                 }
1174                 if (np->nfile.fd != dftfd)
1175                         fprintf(fp, "%d", np->nfile.fd);
1176                 fputs(s, fp);
1177                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1178                         fprintf(fp, "%d", np->ndup.dupfd);
1179                 } else {
1180                         sharg(np->nfile.fname, fp);
1181                 }
1182                 first = 0;
1183         }
1184 }
1185
1186 static void
1187 shtree(union node *n, int ind, char *pfx, FILE *fp)
1188 {
1189         struct nodelist *lp;
1190         const char *s;
1191
1192         if (n == NULL)
1193                 return;
1194
1195         indent(ind, pfx, fp);
1196
1197         if (n == NODE_EOF) {
1198                 fputs("<EOF>", fp);
1199                 return;
1200         }
1201
1202         switch (n->type) {
1203         case NSEMI:
1204                 s = "; ";
1205                 goto binop;
1206         case NAND:
1207                 s = " && ";
1208                 goto binop;
1209         case NOR:
1210                 s = " || ";
1211  binop:
1212                 shtree(n->nbinary.ch1, ind, NULL, fp);
1213                 /* if (ind < 0) */
1214                         fputs(s, fp);
1215                 shtree(n->nbinary.ch2, ind, NULL, fp);
1216                 break;
1217         case NCMD:
1218                 shcmd(n, fp);
1219                 if (ind >= 0)
1220                         putc('\n', fp);
1221                 break;
1222         case NPIPE:
1223                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1224                         shtree(lp->n, 0, NULL, fp);
1225                         if (lp->next)
1226                                 fputs(" | ", fp);
1227                 }
1228                 if (n->npipe.pipe_backgnd)
1229                         fputs(" &", fp);
1230                 if (ind >= 0)
1231                         putc('\n', fp);
1232                 break;
1233         default:
1234                 fprintf(fp, "<node type %d>", n->type);
1235                 if (ind >= 0)
1236                         putc('\n', fp);
1237                 break;
1238         }
1239 }
1240
1241 static void
1242 showtree(union node *n)
1243 {
1244         trace_puts("showtree called\n");
1245         shtree(n, 1, NULL, stderr);
1246 }
1247
1248 #endif /* DEBUG */
1249
1250
1251 /* ============ Parser data */
1252
1253 /*
1254  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1255  */
1256 struct strlist {
1257         struct strlist *next;
1258         char *text;
1259 };
1260
1261 struct alias;
1262
1263 struct strpush {
1264         struct strpush *prev;   /* preceding string on stack */
1265         char *prev_string;
1266         int prev_left_in_line;
1267 #if ENABLE_ASH_ALIAS
1268         struct alias *ap;       /* if push was associated with an alias */
1269 #endif
1270         char *string;           /* remember the string since it may change */
1271
1272         /* Remember last two characters for pungetc. */
1273         int lastc[2];
1274
1275         /* Number of outstanding calls to pungetc. */
1276         int unget;
1277 };
1278
1279 /*
1280  * The parsefile structure pointed to by the global variable parsefile
1281  * contains information about the current file being read.
1282  */
1283 struct parsefile {
1284         struct parsefile *prev; /* preceding file on stack */
1285         int linno;              /* current line */
1286         int pf_fd;              /* file descriptor (or -1 if string) */
1287         int left_in_line;       /* number of chars left in this line */
1288         int left_in_buffer;     /* number of chars left in this buffer past the line */
1289         char *next_to_pgetc;    /* next char in buffer */
1290         char *buf;              /* input buffer */
1291         struct strpush *strpush; /* for pushing strings at this level */
1292         struct strpush basestrpush; /* so pushing one is fast */
1293
1294         /* Remember last two characters for pungetc. */
1295         int lastc[2];
1296
1297         /* Number of outstanding calls to pungetc. */
1298         int unget;
1299 };
1300
1301 static struct parsefile basepf;        /* top level input file */
1302 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1303 static char *commandname;              /* currently executing command */
1304
1305
1306 /* ============ Message printing */
1307
1308 static void
1309 ash_vmsg(const char *msg, va_list ap)
1310 {
1311         fprintf(stderr, "%s: ", arg0);
1312         if (commandname) {
1313                 if (strcmp(arg0, commandname))
1314                         fprintf(stderr, "%s: ", commandname);
1315                 if (!iflag || g_parsefile->pf_fd > 0)
1316                         fprintf(stderr, "line %d: ", errlinno);
1317         }
1318         vfprintf(stderr, msg, ap);
1319         newline_and_flush(stderr);
1320 }
1321
1322 /*
1323  * Exverror is called to raise the error exception.  If the second argument
1324  * is not NULL then error prints an error message using printf style
1325  * formatting.  It then raises the error exception.
1326  */
1327 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1328 static void
1329 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1330 {
1331 #if DEBUG
1332         if (msg) {
1333                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1334                 TRACEV((msg, ap));
1335         } else
1336                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1337         if (msg)
1338 #endif
1339                 ash_vmsg(msg, ap);
1340
1341         flush_stdout_stderr();
1342         raise_exception(cond);
1343         /* NOTREACHED */
1344 }
1345
1346 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1347 static void
1348 ash_msg_and_raise_error(const char *msg, ...)
1349 {
1350         va_list ap;
1351
1352         exitstatus = 2;
1353
1354         va_start(ap, msg);
1355         ash_vmsg_and_raise(EXERROR, msg, ap);
1356         /* NOTREACHED */
1357         va_end(ap);
1358 }
1359
1360 /*
1361  * 'fmt' must be a string literal.
1362  */
1363 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1364
1365 static void raise_error_syntax(const char *) NORETURN;
1366 static void
1367 raise_error_syntax(const char *msg)
1368 {
1369         errlinno = g_parsefile->linno;
1370         ash_msg_and_raise_error("syntax error: %s", msg);
1371         /* NOTREACHED */
1372 }
1373
1374 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1375 static void
1376 ash_msg_and_raise(int cond, const char *msg, ...)
1377 {
1378         va_list ap;
1379
1380         va_start(ap, msg);
1381         ash_vmsg_and_raise(cond, msg, ap);
1382         /* NOTREACHED */
1383         va_end(ap);
1384 }
1385
1386 /*
1387  * error/warning routines for external builtins
1388  */
1389 static void
1390 ash_msg(const char *fmt, ...)
1391 {
1392         va_list ap;
1393
1394         va_start(ap, fmt);
1395         ash_vmsg(fmt, ap);
1396         va_end(ap);
1397 }
1398
1399 /*
1400  * Return a string describing an error.  The returned string may be a
1401  * pointer to a static buffer that will be overwritten on the next call.
1402  * Action describes the operation that got the error.
1403  */
1404 static const char *
1405 errmsg(int e, const char *em)
1406 {
1407         if (e == ENOENT || e == ENOTDIR) {
1408                 return em;
1409         }
1410         return strerror(e);
1411 }
1412
1413
1414 /* ============ Memory allocation */
1415
1416 #if 0
1417 /* I consider these wrappers nearly useless:
1418  * ok, they return you to nearest exception handler, but
1419  * how much memory do you leak in the process, making
1420  * memory starvation worse?
1421  */
1422 static void *
1423 ckrealloc(void * p, size_t nbytes)
1424 {
1425         p = realloc(p, nbytes);
1426         if (!p)
1427                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1428         return p;
1429 }
1430
1431 static void *
1432 ckmalloc(size_t nbytes)
1433 {
1434         return ckrealloc(NULL, nbytes);
1435 }
1436
1437 static void *
1438 ckzalloc(size_t nbytes)
1439 {
1440         return memset(ckmalloc(nbytes), 0, nbytes);
1441 }
1442
1443 static char *
1444 ckstrdup(const char *s)
1445 {
1446         char *p = strdup(s);
1447         if (!p)
1448                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1449         return p;
1450 }
1451 #else
1452 /* Using bbox equivalents. They exit if out of memory */
1453 # define ckrealloc xrealloc
1454 # define ckmalloc  xmalloc
1455 # define ckzalloc  xzalloc
1456 # define ckstrdup  xstrdup
1457 #endif
1458
1459 /*
1460  * It appears that grabstackstr() will barf with such alignments
1461  * because stalloc() will return a string allocated in a new stackblock.
1462  */
1463 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1464 enum {
1465         /* Most machines require the value returned from malloc to be aligned
1466          * in some way.  The following macro will get this right
1467          * on many machines.  */
1468         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1469         /* Minimum size of a block */
1470         MINSIZE = SHELL_ALIGN(504),
1471 };
1472
1473 struct stack_block {
1474         struct stack_block *prev;
1475         char space[MINSIZE];
1476 };
1477
1478 struct stackmark {
1479         struct stack_block *stackp;
1480         char *stacknxt;
1481         size_t stacknleft;
1482 };
1483
1484
1485 struct globals_memstack {
1486         struct stack_block *g_stackp; // = &stackbase;
1487         char *g_stacknxt; // = stackbase.space;
1488         char *sstrend; // = stackbase.space + MINSIZE;
1489         size_t g_stacknleft; // = MINSIZE;
1490         struct stack_block stackbase;
1491 };
1492 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1493 #define G_memstack (*ash_ptr_to_globals_memstack)
1494 #define g_stackp     (G_memstack.g_stackp    )
1495 #define g_stacknxt   (G_memstack.g_stacknxt  )
1496 #define sstrend      (G_memstack.sstrend     )
1497 #define g_stacknleft (G_memstack.g_stacknleft)
1498 #define stackbase    (G_memstack.stackbase   )
1499 #define INIT_G_memstack() do { \
1500         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1501         barrier(); \
1502         g_stackp = &stackbase; \
1503         g_stacknxt = stackbase.space; \
1504         g_stacknleft = MINSIZE; \
1505         sstrend = stackbase.space + MINSIZE; \
1506 } while (0)
1507
1508
1509 #define stackblock()     ((void *)g_stacknxt)
1510 #define stackblocksize() g_stacknleft
1511
1512 /*
1513  * Parse trees for commands are allocated in lifo order, so we use a stack
1514  * to make this more efficient, and also to avoid all sorts of exception
1515  * handling code to handle interrupts in the middle of a parse.
1516  *
1517  * The size 504 was chosen because the Ultrix malloc handles that size
1518  * well.
1519  */
1520 static void *
1521 stalloc(size_t nbytes)
1522 {
1523         char *p;
1524         size_t aligned;
1525
1526         aligned = SHELL_ALIGN(nbytes);
1527         if (aligned > g_stacknleft) {
1528                 size_t len;
1529                 size_t blocksize;
1530                 struct stack_block *sp;
1531
1532                 blocksize = aligned;
1533                 if (blocksize < MINSIZE)
1534                         blocksize = MINSIZE;
1535                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1536                 if (len < blocksize)
1537                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1538                 INT_OFF;
1539                 sp = ckmalloc(len);
1540                 sp->prev = g_stackp;
1541                 g_stacknxt = sp->space;
1542                 g_stacknleft = blocksize;
1543                 sstrend = g_stacknxt + blocksize;
1544                 g_stackp = sp;
1545                 INT_ON;
1546         }
1547         p = g_stacknxt;
1548         g_stacknxt += aligned;
1549         g_stacknleft -= aligned;
1550         return p;
1551 }
1552
1553 static void *
1554 stzalloc(size_t nbytes)
1555 {
1556         return memset(stalloc(nbytes), 0, nbytes);
1557 }
1558
1559 static void
1560 stunalloc(void *p)
1561 {
1562 #if DEBUG
1563         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1564                 write(STDERR_FILENO, "stunalloc\n", 10);
1565                 abort();
1566         }
1567 #endif
1568         g_stacknleft += g_stacknxt - (char *)p;
1569         g_stacknxt = p;
1570 }
1571
1572 /*
1573  * Like strdup but works with the ash stack.
1574  */
1575 static char *
1576 sstrdup(const char *p)
1577 {
1578         size_t len = strlen(p) + 1;
1579         return memcpy(stalloc(len), p, len);
1580 }
1581
1582 static ALWAYS_INLINE void
1583 grabstackblock(size_t len)
1584 {
1585         stalloc(len);
1586 }
1587
1588 static void
1589 pushstackmark(struct stackmark *mark, size_t len)
1590 {
1591         mark->stackp = g_stackp;
1592         mark->stacknxt = g_stacknxt;
1593         mark->stacknleft = g_stacknleft;
1594         grabstackblock(len);
1595 }
1596
1597 static void
1598 setstackmark(struct stackmark *mark)
1599 {
1600         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1601 }
1602
1603 static void
1604 popstackmark(struct stackmark *mark)
1605 {
1606         struct stack_block *sp;
1607
1608         if (!mark->stackp)
1609                 return;
1610
1611         INT_OFF;
1612         while (g_stackp != mark->stackp) {
1613                 sp = g_stackp;
1614                 g_stackp = sp->prev;
1615                 free(sp);
1616         }
1617         g_stacknxt = mark->stacknxt;
1618         g_stacknleft = mark->stacknleft;
1619         sstrend = mark->stacknxt + mark->stacknleft;
1620         INT_ON;
1621 }
1622
1623 /*
1624  * When the parser reads in a string, it wants to stick the string on the
1625  * stack and only adjust the stack pointer when it knows how big the
1626  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1627  * of space on top of the stack and stackblocklen returns the length of
1628  * this block.  Growstackblock will grow this space by at least one byte,
1629  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1630  * part of the block that has been used.
1631  */
1632 static void
1633 growstackblock(void)
1634 {
1635         size_t newlen;
1636
1637         newlen = g_stacknleft * 2;
1638         if (newlen < g_stacknleft)
1639                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1640         if (newlen < 128)
1641                 newlen += 128;
1642
1643         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1644                 struct stack_block *sp;
1645                 struct stack_block *prevstackp;
1646                 size_t grosslen;
1647
1648                 INT_OFF;
1649                 sp = g_stackp;
1650                 prevstackp = sp->prev;
1651                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1652                 sp = ckrealloc(sp, grosslen);
1653                 sp->prev = prevstackp;
1654                 g_stackp = sp;
1655                 g_stacknxt = sp->space;
1656                 g_stacknleft = newlen;
1657                 sstrend = sp->space + newlen;
1658                 INT_ON;
1659         } else {
1660                 char *oldspace = g_stacknxt;
1661                 size_t oldlen = g_stacknleft;
1662                 char *p = stalloc(newlen);
1663
1664                 /* free the space we just allocated */
1665                 g_stacknxt = memcpy(p, oldspace, oldlen);
1666                 g_stacknleft += newlen;
1667         }
1668 }
1669
1670 /*
1671  * The following routines are somewhat easier to use than the above.
1672  * The user declares a variable of type STACKSTR, which may be declared
1673  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1674  * the user uses the macro STPUTC to add characters to the string.  In
1675  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1676  * grown as necessary.  When the user is done, she can just leave the
1677  * string there and refer to it using stackblock().  Or she can allocate
1678  * the space for it using grabstackstr().  If it is necessary to allow
1679  * someone else to use the stack temporarily and then continue to grow
1680  * the string, the user should use grabstack to allocate the space, and
1681  * then call ungrabstr(p) to return to the previous mode of operation.
1682  *
1683  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1684  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1685  * is space for at least one character.
1686  */
1687 static void *
1688 growstackstr(void)
1689 {
1690         size_t len = stackblocksize();
1691         growstackblock();
1692         return (char *)stackblock() + len;
1693 }
1694
1695 /*
1696  * Called from CHECKSTRSPACE.
1697  */
1698 static char *
1699 makestrspace(size_t newlen, char *p)
1700 {
1701         size_t len = p - g_stacknxt;
1702         size_t size;
1703
1704         for (;;) {
1705                 size_t nleft;
1706
1707                 size = stackblocksize();
1708                 nleft = size - len;
1709                 if (nleft >= newlen)
1710                         break;
1711                 growstackblock();
1712         }
1713         return (char *)stackblock() + len;
1714 }
1715
1716 static char *
1717 stack_nputstr(const char *s, size_t n, char *p)
1718 {
1719         p = makestrspace(n, p);
1720         p = (char *)mempcpy(p, s, n);
1721         return p;
1722 }
1723
1724 static char *
1725 stack_putstr(const char *s, char *p)
1726 {
1727         return stack_nputstr(s, strlen(s), p);
1728 }
1729
1730 static char *
1731 _STPUTC(int c, char *p)
1732 {
1733         if (p == sstrend)
1734                 p = growstackstr();
1735         *p++ = c;
1736         return p;
1737 }
1738
1739 #define STARTSTACKSTR(p)        ((p) = stackblock())
1740 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1741 #define CHECKSTRSPACE(n, p) do { \
1742         char *q = (p); \
1743         size_t l = (n); \
1744         size_t m = sstrend - q; \
1745         if (l > m) \
1746                 (p) = makestrspace(l, q); \
1747 } while (0)
1748 #define USTPUTC(c, p)           (*(p)++ = (c))
1749 #define STACKSTRNUL(p) do { \
1750         if ((p) == sstrend) \
1751                 (p) = growstackstr(); \
1752         *(p) = '\0'; \
1753 } while (0)
1754 #define STUNPUTC(p)             (--(p))
1755 #define STTOPC(p)               ((p)[-1])
1756 #define STADJUST(amount, p)     ((p) += (amount))
1757
1758 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1759 #define ungrabstackstr(s, p)    stunalloc(s)
1760 #define stackstrend()           ((void *)sstrend)
1761
1762
1763 /* ============ String helpers */
1764
1765 /*
1766  * prefix -- see if pfx is a prefix of string.
1767  */
1768 static char *
1769 prefix(const char *string, const char *pfx)
1770 {
1771         while (*pfx) {
1772                 if (*pfx++ != *string++)
1773                         return NULL;
1774         }
1775         return (char *) string;
1776 }
1777
1778 /*
1779  * Check for a valid number.  This should be elsewhere.
1780  */
1781 static int
1782 is_number(const char *p)
1783 {
1784         do {
1785                 if (!isdigit(*p))
1786                         return 0;
1787         } while (*++p != '\0');
1788         return 1;
1789 }
1790
1791 /*
1792  * Convert a string of digits to an integer, printing an error message on
1793  * failure.
1794  */
1795 static int
1796 number(const char *s)
1797 {
1798         if (!is_number(s))
1799                 ash_msg_and_raise_error(msg_illnum, s);
1800         return atoi(s);
1801 }
1802
1803 /*
1804  * Produce a single quoted string suitable as input to the shell.
1805  * The return string is allocated on the stack.
1806  */
1807 static char *
1808 single_quote(const char *s)
1809 {
1810         char *p;
1811
1812         STARTSTACKSTR(p);
1813
1814         do {
1815                 char *q;
1816                 size_t len;
1817
1818                 len = strchrnul(s, '\'') - s;
1819
1820                 q = p = makestrspace(len + 3, p);
1821
1822                 *q++ = '\'';
1823                 q = (char *)mempcpy(q, s, len);
1824                 *q++ = '\'';
1825                 s += len;
1826
1827                 STADJUST(q - p, p);
1828
1829                 if (*s != '\'')
1830                         break;
1831                 len = 0;
1832                 do len++; while (*++s == '\'');
1833
1834                 q = p = makestrspace(len + 3, p);
1835
1836                 *q++ = '"';
1837                 q = (char *)mempcpy(q, s - len, len);
1838                 *q++ = '"';
1839
1840                 STADJUST(q - p, p);
1841         } while (*s);
1842
1843         USTPUTC('\0', p);
1844
1845         return stackblock();
1846 }
1847
1848 /*
1849  * Produce a possibly single quoted string suitable as input to the shell.
1850  * If quoting was done, the return string is allocated on the stack,
1851  * otherwise a pointer to the original string is returned.
1852  */
1853 static const char *
1854 maybe_single_quote(const char *s)
1855 {
1856         const char *p = s;
1857
1858         while (*p) {
1859                 /* Assuming ACSII */
1860                 /* quote ctrl_chars space !"#$%&'()* */
1861                 if (*p < '+')
1862                         goto need_quoting;
1863                 /* quote ;<=>? */
1864                 if (*p >= ';' && *p <= '?')
1865                         goto need_quoting;
1866                 /* quote `[\ */
1867                 if (*p == '`')
1868                         goto need_quoting;
1869                 if (*p == '[')
1870                         goto need_quoting;
1871                 if (*p == '\\')
1872                         goto need_quoting;
1873                 /* quote {|}~ DEL and high bytes */
1874                 if (*p > 'z')
1875                         goto need_quoting;
1876                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1877                 /* TODO: maybe avoid quoting % */
1878                 p++;
1879         }
1880         return s;
1881
1882  need_quoting:
1883         return single_quote(s);
1884 }
1885
1886
1887 /* ============ nextopt */
1888
1889 static char **argptr;                  /* argument list for builtin commands */
1890 static char *optionarg;                /* set by nextopt (like getopt) */
1891 static char *optptr;                   /* used by nextopt */
1892
1893 /*
1894  * XXX - should get rid of. Have all builtins use getopt(3).
1895  * The library getopt must have the BSD extension static variable
1896  * "optreset", otherwise it can't be used within the shell safely.
1897  *
1898  * Standard option processing (a la getopt) for builtin routines.
1899  * The only argument that is passed to nextopt is the option string;
1900  * the other arguments are unnecessary. It returns the character,
1901  * or '\0' on end of input.
1902  */
1903 static int
1904 nextopt(const char *optstring)
1905 {
1906         char *p;
1907         const char *q;
1908         char c;
1909
1910         p = optptr;
1911         if (p == NULL || *p == '\0') {
1912                 /* We ate entire "-param", take next one */
1913                 p = *argptr;
1914                 if (p == NULL)
1915                         return '\0';
1916                 if (*p != '-')
1917                         return '\0';
1918                 if (*++p == '\0') /* just "-" ? */
1919                         return '\0';
1920                 argptr++;
1921                 if (LONE_DASH(p)) /* "--" ? */
1922                         return '\0';
1923                 /* p => next "-param" */
1924         }
1925         /* p => some option char in the middle of a "-param" */
1926         c = *p++;
1927         for (q = optstring; *q != c;) {
1928                 if (*q == '\0')
1929                         ash_msg_and_raise_error("illegal option -%c", c);
1930                 if (*++q == ':')
1931                         q++;
1932         }
1933         if (*++q == ':') {
1934                 if (*p == '\0') {
1935                         p = *argptr++;
1936                         if (p == NULL)
1937                                 ash_msg_and_raise_error("no arg for -%c option", c);
1938                 }
1939                 optionarg = p;
1940                 p = NULL;
1941         }
1942         optptr = p;
1943         return c;
1944 }
1945
1946
1947 /* ============ Shell variables */
1948
1949 struct shparam {
1950         int nparam;             /* # of positional parameters (without $0) */
1951 #if ENABLE_ASH_GETOPTS
1952         int optind;             /* next parameter to be processed by getopts */
1953         int optoff;             /* used by getopts */
1954 #endif
1955         unsigned char malloced; /* if parameter list dynamically allocated */
1956         char **p;               /* parameter list */
1957 };
1958
1959 /*
1960  * Free the list of positional parameters.
1961  */
1962 static void
1963 freeparam(volatile struct shparam *param)
1964 {
1965         if (param->malloced) {
1966                 char **ap, **ap1;
1967                 ap = ap1 = param->p;
1968                 while (*ap)
1969                         free(*ap++);
1970                 free(ap1);
1971         }
1972 }
1973
1974 #if ENABLE_ASH_GETOPTS
1975 static void FAST_FUNC getoptsreset(const char *value);
1976 #endif
1977
1978 struct var {
1979         struct var *next;               /* next entry in hash list */
1980         int flags;                      /* flags are defined above */
1981         const char *var_text;           /* name=value */
1982         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1983                                         /* the variable gets set/unset */
1984 };
1985
1986 struct localvar {
1987         struct localvar *next;          /* next local variable in list */
1988         struct var *vp;                 /* the variable that was made local */
1989         int flags;                      /* saved flags */
1990         const char *text;               /* saved text */
1991 };
1992
1993 /* flags */
1994 #define VEXPORT         0x01    /* variable is exported */
1995 #define VREADONLY       0x02    /* variable cannot be modified */
1996 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1997 #define VTEXTFIXED      0x08    /* text is statically allocated */
1998 #define VSTACK          0x10    /* text is allocated on the stack */
1999 #define VUNSET          0x20    /* the variable is not set */
2000 #define VNOFUNC         0x40    /* don't call the callback function */
2001 #define VNOSET          0x80    /* do not set variable - just readonly test */
2002 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2003 #if ENABLE_ASH_RANDOM_SUPPORT
2004 # define VDYNAMIC       0x200   /* dynamic variable */
2005 #else
2006 # define VDYNAMIC       0
2007 #endif
2008
2009
2010 /* Need to be before varinit_data[] */
2011 #if ENABLE_LOCALE_SUPPORT
2012 static void FAST_FUNC
2013 change_lc_all(const char *value)
2014 {
2015         if (value && *value != '\0')
2016                 setlocale(LC_ALL, value);
2017 }
2018 static void FAST_FUNC
2019 change_lc_ctype(const char *value)
2020 {
2021         if (value && *value != '\0')
2022                 setlocale(LC_CTYPE, value);
2023 }
2024 #endif
2025 #if ENABLE_ASH_MAIL
2026 static void chkmail(void);
2027 static void changemail(const char *var_value) FAST_FUNC;
2028 #else
2029 # define chkmail()  ((void)0)
2030 #endif
2031 static void changepath(const char *) FAST_FUNC;
2032 #if ENABLE_ASH_RANDOM_SUPPORT
2033 static void change_random(const char *) FAST_FUNC;
2034 #endif
2035
2036 static const struct {
2037         int flags;
2038         const char *var_text;
2039         void (*var_func)(const char *) FAST_FUNC;
2040 } varinit_data[] = {
2041         /*
2042          * Note: VEXPORT would not work correctly here for NOFORK applets:
2043          * some environment strings may be constant.
2044          */
2045         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2046 #if ENABLE_ASH_MAIL
2047         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2048         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2049 #endif
2050         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2051         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2052         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2053         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2054 #if ENABLE_ASH_GETOPTS
2055         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2056 #endif
2057         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2058 #if ENABLE_ASH_RANDOM_SUPPORT
2059         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2060 #endif
2061 #if ENABLE_LOCALE_SUPPORT
2062         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2063         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2064 #endif
2065 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2066         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2067 #endif
2068 };
2069
2070 struct redirtab;
2071
2072 struct globals_var {
2073         struct shparam shellparam;      /* $@ current positional parameters */
2074         struct redirtab *redirlist;
2075         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2076         struct var *vartab[VTABSIZE];
2077         struct var varinit[ARRAY_SIZE(varinit_data)];
2078         int lineno;
2079         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2080 };
2081 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2082 #define G_var (*ash_ptr_to_globals_var)
2083 #define shellparam    (G_var.shellparam   )
2084 //#define redirlist     (G_var.redirlist    )
2085 #define preverrout_fd (G_var.preverrout_fd)
2086 #define vartab        (G_var.vartab       )
2087 #define varinit       (G_var.varinit      )
2088 #define lineno        (G_var.lineno       )
2089 #define linenovar     (G_var.linenovar    )
2090 #define vifs      varinit[0]
2091 #if ENABLE_ASH_MAIL
2092 # define vmail    (&vifs)[1]
2093 # define vmpath   (&vmail)[1]
2094 # define vpath    (&vmpath)[1]
2095 #else
2096 # define vpath    (&vifs)[1]
2097 #endif
2098 #define vps1      (&vpath)[1]
2099 #define vps2      (&vps1)[1]
2100 #define vps4      (&vps2)[1]
2101 #if ENABLE_ASH_GETOPTS
2102 # define voptind  (&vps4)[1]
2103 # define vlineno  (&voptind)[1]
2104 # if ENABLE_ASH_RANDOM_SUPPORT
2105 #  define vrandom (&vlineno)[1]
2106 # endif
2107 #else
2108 # define vlineno  (&vps4)[1]
2109 # if ENABLE_ASH_RANDOM_SUPPORT
2110 #  define vrandom (&vlineno)[1]
2111 # endif
2112 #endif
2113 #define INIT_G_var() do { \
2114         unsigned i; \
2115         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2116         barrier(); \
2117         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2118                 varinit[i].flags    = varinit_data[i].flags; \
2119                 varinit[i].var_text = varinit_data[i].var_text; \
2120                 varinit[i].var_func = varinit_data[i].var_func; \
2121         } \
2122         strcpy(linenovar, "LINENO="); \
2123         vlineno.var_text = linenovar; \
2124 } while (0)
2125
2126 /*
2127  * The following macros access the values of the above variables.
2128  * They have to skip over the name.  They return the null string
2129  * for unset variables.
2130  */
2131 #define ifsval()        (vifs.var_text + 4)
2132 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2133 #if ENABLE_ASH_MAIL
2134 # define mailval()      (vmail.var_text + 5)
2135 # define mpathval()     (vmpath.var_text + 9)
2136 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2137 #endif
2138 #define pathval()       (vpath.var_text + 5)
2139 #define ps1val()        (vps1.var_text + 4)
2140 #define ps2val()        (vps2.var_text + 4)
2141 #define ps4val()        (vps4.var_text + 4)
2142 #if ENABLE_ASH_GETOPTS
2143 # define optindval()    (voptind.var_text + 7)
2144 #endif
2145
2146 #if ENABLE_ASH_GETOPTS
2147 static void FAST_FUNC
2148 getoptsreset(const char *value)
2149 {
2150         shellparam.optind = 1;
2151         if (is_number(value))
2152                 shellparam.optind = number(value) ?: 1;
2153         shellparam.optoff = -1;
2154 }
2155 #endif
2156
2157 /*
2158  * Compares two strings up to the first = or '\0'.  The first
2159  * string must be terminated by '='; the second may be terminated by
2160  * either '=' or '\0'.
2161  */
2162 static int
2163 varcmp(const char *p, const char *q)
2164 {
2165         int c, d;
2166
2167         while ((c = *p) == (d = *q)) {
2168                 if (c == '\0' || c == '=')
2169                         goto out;
2170                 p++;
2171                 q++;
2172         }
2173         if (c == '=')
2174                 c = '\0';
2175         if (d == '=')
2176                 d = '\0';
2177  out:
2178         return c - d;
2179 }
2180
2181 /*
2182  * Find the appropriate entry in the hash table from the name.
2183  */
2184 static struct var **
2185 hashvar(const char *p)
2186 {
2187         unsigned hashval;
2188
2189         hashval = ((unsigned char) *p) << 4;
2190         while (*p && *p != '=')
2191                 hashval += (unsigned char) *p++;
2192         return &vartab[hashval % VTABSIZE];
2193 }
2194
2195 static int
2196 vpcmp(const void *a, const void *b)
2197 {
2198         return varcmp(*(const char **)a, *(const char **)b);
2199 }
2200
2201 /*
2202  * This routine initializes the builtin variables.
2203  */
2204 static void
2205 initvar(void)
2206 {
2207         struct var *vp;
2208         struct var *end;
2209         struct var **vpp;
2210
2211         /*
2212          * PS1 depends on uid
2213          */
2214 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2215         vps1.var_text = "PS1=\\w \\$ ";
2216 #else
2217         if (!geteuid())
2218                 vps1.var_text = "PS1=# ";
2219 #endif
2220         vp = varinit;
2221         end = vp + ARRAY_SIZE(varinit);
2222         do {
2223                 vpp = hashvar(vp->var_text);
2224                 vp->next = *vpp;
2225                 *vpp = vp;
2226         } while (++vp < end);
2227 }
2228
2229 static struct var **
2230 findvar(struct var **vpp, const char *name)
2231 {
2232         for (; *vpp; vpp = &(*vpp)->next) {
2233                 if (varcmp((*vpp)->var_text, name) == 0) {
2234                         break;
2235                 }
2236         }
2237         return vpp;
2238 }
2239
2240 /*
2241  * Find the value of a variable.  Returns NULL if not set.
2242  */
2243 static const char* FAST_FUNC
2244 lookupvar(const char *name)
2245 {
2246         struct var *v;
2247
2248         v = *findvar(hashvar(name), name);
2249         if (v) {
2250 #if ENABLE_ASH_RANDOM_SUPPORT
2251         /*
2252          * Dynamic variables are implemented roughly the same way they are
2253          * in bash. Namely, they're "special" so long as they aren't unset.
2254          * As soon as they're unset, they're no longer dynamic, and dynamic
2255          * lookup will no longer happen at that point. -- PFM.
2256          */
2257                 if (v->flags & VDYNAMIC)
2258                         v->var_func(NULL);
2259 #endif
2260                 if (!(v->flags & VUNSET)) {
2261                         if (v == &vlineno && v->var_text == linenovar) {
2262                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2263                         }
2264                         return var_end(v->var_text);
2265                 }
2266         }
2267         return NULL;
2268 }
2269
2270 #if ENABLE_UNICODE_SUPPORT
2271 static void
2272 reinit_unicode_for_ash(void)
2273 {
2274         /* Unicode support should be activated even if LANG is set
2275          * _during_ shell execution, not only if it was set when
2276          * shell was started. Therefore, re-check LANG every time:
2277          */
2278         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2279          || ENABLE_UNICODE_USING_LOCALE
2280         ) {
2281                 const char *s = lookupvar("LC_ALL");
2282                 if (!s) s = lookupvar("LC_CTYPE");
2283                 if (!s) s = lookupvar("LANG");
2284                 reinit_unicode(s);
2285         }
2286 }
2287 #else
2288 # define reinit_unicode_for_ash() ((void)0)
2289 #endif
2290
2291 /*
2292  * Search the environment of a builtin command.
2293  */
2294 static ALWAYS_INLINE const char *
2295 bltinlookup(const char *name)
2296 {
2297         return lookupvar(name);
2298 }
2299
2300 /*
2301  * Same as setvar except that the variable and value are passed in
2302  * the first argument as name=value.  Since the first argument will
2303  * be actually stored in the table, it should not be a string that
2304  * will go away.
2305  * Called with interrupts off.
2306  */
2307 static struct var *
2308 setvareq(char *s, int flags)
2309 {
2310         struct var *vp, **vpp;
2311
2312         vpp = hashvar(s);
2313         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2314         vpp = findvar(vpp, s);
2315         vp = *vpp;
2316         if (vp) {
2317                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2318                         const char *n;
2319
2320                         if (flags & VNOSAVE)
2321                                 free(s);
2322                         n = vp->var_text;
2323                         exitstatus = 1;
2324                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2325                 }
2326
2327                 if (flags & VNOSET)
2328                         goto out;
2329
2330                 if (vp->var_func && !(flags & VNOFUNC))
2331                         vp->var_func(var_end(s));
2332
2333                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2334                         free((char*)vp->var_text);
2335
2336                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2337                         *vpp = vp->next;
2338                         free(vp);
2339  out_free:
2340                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2341                                 free(s);
2342                         goto out;
2343                 }
2344
2345                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2346         } else {
2347                 /* variable s is not found */
2348                 if (flags & VNOSET)
2349                         goto out;
2350                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2351                         goto out_free;
2352                 vp = ckzalloc(sizeof(*vp));
2353                 vp->next = *vpp;
2354                 /*vp->func = NULL; - ckzalloc did it */
2355                 *vpp = vp;
2356         }
2357         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2358                 s = ckstrdup(s);
2359         vp->var_text = s;
2360         vp->flags = flags;
2361
2362  out:
2363         return vp;
2364 }
2365
2366 /*
2367  * Set the value of a variable.  The flags argument is ored with the
2368  * flags of the variable.  If val is NULL, the variable is unset.
2369  */
2370 static struct var *
2371 setvar(const char *name, const char *val, int flags)
2372 {
2373         const char *q;
2374         char *p;
2375         char *nameeq;
2376         size_t namelen;
2377         size_t vallen;
2378         struct var *vp;
2379
2380         q = endofname(name);
2381         p = strchrnul(q, '=');
2382         namelen = p - name;
2383         if (!namelen || p != q)
2384                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2385         vallen = 0;
2386         if (val == NULL) {
2387                 flags |= VUNSET;
2388         } else {
2389                 vallen = strlen(val);
2390         }
2391
2392         INT_OFF;
2393         nameeq = ckmalloc(namelen + vallen + 2);
2394         p = mempcpy(nameeq, name, namelen);
2395         if (val) {
2396                 *p++ = '=';
2397                 p = mempcpy(p, val, vallen);
2398         }
2399         *p = '\0';
2400         vp = setvareq(nameeq, flags | VNOSAVE);
2401         INT_ON;
2402
2403         return vp;
2404 }
2405
2406 static void FAST_FUNC
2407 setvar0(const char *name, const char *val)
2408 {
2409         setvar(name, val, 0);
2410 }
2411
2412 /*
2413  * Unset the specified variable.
2414  */
2415 static void
2416 unsetvar(const char *s)
2417 {
2418         setvar(s, NULL, 0);
2419 }
2420
2421 /*
2422  * Process a linked list of variable assignments.
2423  */
2424 static void
2425 listsetvar(struct strlist *list_set_var, int flags)
2426 {
2427         struct strlist *lp = list_set_var;
2428
2429         if (!lp)
2430                 return;
2431         INT_OFF;
2432         do {
2433                 setvareq(lp->text, flags);
2434                 lp = lp->next;
2435         } while (lp);
2436         INT_ON;
2437 }
2438
2439 /*
2440  * Generate a list of variables satisfying the given conditions.
2441  */
2442 #if !ENABLE_FEATURE_SH_NOFORK
2443 # define listvars(on, off, lp, end) listvars(on, off, end)
2444 #endif
2445 static char **
2446 listvars(int on, int off, struct strlist *lp, char ***end)
2447 {
2448         struct var **vpp;
2449         struct var *vp;
2450         char **ep;
2451         int mask;
2452
2453         STARTSTACKSTR(ep);
2454         vpp = vartab;
2455         mask = on | off;
2456         do {
2457                 for (vp = *vpp; vp; vp = vp->next) {
2458                         if ((vp->flags & mask) == on) {
2459 #if ENABLE_FEATURE_SH_NOFORK
2460                                 /* If variable with the same name is both
2461                                  * exported and temporarily set for a command:
2462                                  *  export ZVAR=5
2463                                  *  ZVAR=6 printenv
2464                                  * then "ZVAR=6" will be both in vartab and
2465                                  * lp lists. Do not pass it twice to printenv.
2466                                  */
2467                                 struct strlist *lp1 = lp;
2468                                 while (lp1) {
2469                                         if (strcmp(lp1->text, vp->var_text) == 0)
2470                                                 goto skip;
2471                                         lp1 = lp1->next;
2472                                 }
2473 #endif
2474                                 if (ep == stackstrend())
2475                                         ep = growstackstr();
2476                                 *ep++ = (char*)vp->var_text;
2477 #if ENABLE_FEATURE_SH_NOFORK
2478  skip: ;
2479 #endif
2480                         }
2481                 }
2482         } while (++vpp < vartab + VTABSIZE);
2483
2484 #if ENABLE_FEATURE_SH_NOFORK
2485         while (lp) {
2486                 if (ep == stackstrend())
2487                         ep = growstackstr();
2488                 *ep++ = lp->text;
2489                 lp = lp->next;
2490         }
2491 #endif
2492
2493         if (ep == stackstrend())
2494                 ep = growstackstr();
2495         if (end)
2496                 *end = ep;
2497         *ep++ = NULL;
2498         return grabstackstr(ep);
2499 }
2500
2501
2502 /* ============ Path search helper
2503  *
2504  * The variable path (passed by reference) should be set to the start
2505  * of the path before the first call; path_advance will update
2506  * this value as it proceeds.  Successive calls to path_advance will return
2507  * the possible path expansions in sequence.  If an option (indicated by
2508  * a percent sign) appears in the path entry then the global variable
2509  * pathopt will be set to point to it; otherwise pathopt will be set to
2510  * NULL.
2511  */
2512 static const char *pathopt;     /* set by path_advance */
2513
2514 static char *
2515 path_advance(const char **path, const char *name)
2516 {
2517         const char *p;
2518         char *q;
2519         const char *start;
2520         size_t len;
2521
2522         if (*path == NULL)
2523                 return NULL;
2524         start = *path;
2525         for (p = start; *p && *p != ':' && *p != '%'; p++)
2526                 continue;
2527         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2528         while (stackblocksize() < len)
2529                 growstackblock();
2530         q = stackblock();
2531         if (p != start) {
2532                 q = mempcpy(q, start, p - start);
2533                 *q++ = '/';
2534         }
2535         strcpy(q, name);
2536         pathopt = NULL;
2537         if (*p == '%') {
2538                 pathopt = ++p;
2539                 while (*p && *p != ':')
2540                         p++;
2541         }
2542         if (*p == ':')
2543                 *path = p + 1;
2544         else
2545                 *path = NULL;
2546         return stalloc(len);
2547 }
2548
2549
2550 /* ============ Prompt */
2551
2552 static smallint doprompt;                   /* if set, prompt the user */
2553 static smallint needprompt;                 /* true if interactive and at start of line */
2554
2555 #if ENABLE_FEATURE_EDITING
2556 static line_input_t *line_input_state;
2557 static const char *cmdedit_prompt;
2558 static void
2559 putprompt(const char *s)
2560 {
2561         if (ENABLE_ASH_EXPAND_PRMT) {
2562                 free((char*)cmdedit_prompt);
2563                 cmdedit_prompt = ckstrdup(s);
2564                 return;
2565         }
2566         cmdedit_prompt = s;
2567 }
2568 #else
2569 static void
2570 putprompt(const char *s)
2571 {
2572         out2str(s);
2573 }
2574 #endif
2575
2576 /* expandstr() needs parsing machinery, so it is far away ahead... */
2577 static const char *expandstr(const char *ps, int syntax_type);
2578 /* Values for syntax param */
2579 #define BASESYNTAX 0    /* not in quotes */
2580 #define DQSYNTAX   1    /* in double quotes */
2581 #define SQSYNTAX   2    /* in single quotes */
2582 #define ARISYNTAX  3    /* in arithmetic */
2583 #if ENABLE_ASH_EXPAND_PRMT
2584 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2585 #endif
2586 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2587
2588 /*
2589  * called by editline -- any expansions to the prompt should be added here.
2590  */
2591 static void
2592 setprompt_if(smallint do_set, int whichprompt)
2593 {
2594         const char *prompt;
2595         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2596
2597         if (!do_set)
2598                 return;
2599
2600         needprompt = 0;
2601
2602         switch (whichprompt) {
2603         case 1:
2604                 prompt = ps1val();
2605                 break;
2606         case 2:
2607                 prompt = ps2val();
2608                 break;
2609         default:                        /* 0 */
2610                 prompt = nullstr;
2611         }
2612 #if ENABLE_ASH_EXPAND_PRMT
2613         pushstackmark(&smark, stackblocksize());
2614         putprompt(expandstr(prompt, PSSYNTAX));
2615         popstackmark(&smark);
2616 #else
2617         putprompt(prompt);
2618 #endif
2619 }
2620
2621
2622 /* ============ The cd and pwd commands */
2623
2624 #define CD_PHYSICAL 1
2625 #define CD_PRINT 2
2626
2627 static int
2628 cdopt(void)
2629 {
2630         int flags = 0;
2631         int i, j;
2632
2633         j = 'L';
2634         while ((i = nextopt("LP")) != '\0') {
2635                 if (i != j) {
2636                         flags ^= CD_PHYSICAL;
2637                         j = i;
2638                 }
2639         }
2640
2641         return flags;
2642 }
2643
2644 /*
2645  * Update curdir (the name of the current directory) in response to a
2646  * cd command.
2647  */
2648 static const char *
2649 updatepwd(const char *dir)
2650 {
2651         char *new;
2652         char *p;
2653         char *cdcomppath;
2654         const char *lim;
2655
2656         cdcomppath = sstrdup(dir);
2657         STARTSTACKSTR(new);
2658         if (*dir != '/') {
2659                 if (curdir == nullstr)
2660                         return 0;
2661                 new = stack_putstr(curdir, new);
2662         }
2663         new = makestrspace(strlen(dir) + 2, new);
2664         lim = (char *)stackblock() + 1;
2665         if (*dir != '/') {
2666                 if (new[-1] != '/')
2667                         USTPUTC('/', new);
2668                 if (new > lim && *lim == '/')
2669                         lim++;
2670         } else {
2671                 USTPUTC('/', new);
2672                 cdcomppath++;
2673                 if (dir[1] == '/' && dir[2] != '/') {
2674                         USTPUTC('/', new);
2675                         cdcomppath++;
2676                         lim++;
2677                 }
2678         }
2679         p = strtok(cdcomppath, "/");
2680         while (p) {
2681                 switch (*p) {
2682                 case '.':
2683                         if (p[1] == '.' && p[2] == '\0') {
2684                                 while (new > lim) {
2685                                         STUNPUTC(new);
2686                                         if (new[-1] == '/')
2687                                                 break;
2688                                 }
2689                                 break;
2690                         }
2691                         if (p[1] == '\0')
2692                                 break;
2693                         /* fall through */
2694                 default:
2695                         new = stack_putstr(p, new);
2696                         USTPUTC('/', new);
2697                 }
2698                 p = strtok(NULL, "/");
2699         }
2700         if (new > lim)
2701                 STUNPUTC(new);
2702         *new = 0;
2703         return stackblock();
2704 }
2705
2706 /*
2707  * Find out what the current directory is. If we already know the current
2708  * directory, this routine returns immediately.
2709  */
2710 static char *
2711 getpwd(void)
2712 {
2713         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2714         return dir ? dir : nullstr;
2715 }
2716
2717 static void
2718 setpwd(const char *val, int setold)
2719 {
2720         char *oldcur, *dir;
2721
2722         oldcur = dir = curdir;
2723
2724         if (setold) {
2725                 setvar("OLDPWD", oldcur, VEXPORT);
2726         }
2727         INT_OFF;
2728         if (physdir != nullstr) {
2729                 if (physdir != oldcur)
2730                         free(physdir);
2731                 physdir = nullstr;
2732         }
2733         if (oldcur == val || !val) {
2734                 char *s = getpwd();
2735                 physdir = s;
2736                 if (!val)
2737                         dir = s;
2738         } else
2739                 dir = ckstrdup(val);
2740         if (oldcur != dir && oldcur != nullstr) {
2741                 free(oldcur);
2742         }
2743         curdir = dir;
2744         INT_ON;
2745         setvar("PWD", dir, VEXPORT);
2746 }
2747
2748 static void hashcd(void);
2749
2750 /*
2751  * Actually do the chdir.  We also call hashcd to let other routines
2752  * know that the current directory has changed.
2753  */
2754 static int
2755 docd(const char *dest, int flags)
2756 {
2757         const char *dir = NULL;
2758         int err;
2759
2760         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2761
2762         INT_OFF;
2763         if (!(flags & CD_PHYSICAL)) {
2764                 dir = updatepwd(dest);
2765                 if (dir)
2766                         dest = dir;
2767         }
2768         err = chdir(dest);
2769         if (err)
2770                 goto out;
2771         setpwd(dir, 1);
2772         hashcd();
2773  out:
2774         INT_ON;
2775         return err;
2776 }
2777
2778 static int FAST_FUNC
2779 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2780 {
2781         const char *dest;
2782         const char *path;
2783         const char *p;
2784         char c;
2785         struct stat statb;
2786         int flags;
2787
2788         flags = cdopt();
2789         dest = *argptr;
2790         if (!dest)
2791                 dest = bltinlookup("HOME");
2792         else if (LONE_DASH(dest)) {
2793                 dest = bltinlookup("OLDPWD");
2794                 flags |= CD_PRINT;
2795         }
2796         if (!dest)
2797                 dest = nullstr;
2798         if (*dest == '/')
2799                 goto step6;
2800         if (*dest == '.') {
2801                 c = dest[1];
2802  dotdot:
2803                 switch (c) {
2804                 case '\0':
2805                 case '/':
2806                         goto step6;
2807                 case '.':
2808                         c = dest[2];
2809                         if (c != '.')
2810                                 goto dotdot;
2811                 }
2812         }
2813         if (!*dest)
2814                 dest = ".";
2815         path = bltinlookup("CDPATH");
2816         while (path) {
2817                 c = *path;
2818                 p = path_advance(&path, dest);
2819                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2820                         if (c && c != ':')
2821                                 flags |= CD_PRINT;
2822  docd:
2823                         if (!docd(p, flags))
2824                                 goto out;
2825                         goto err;
2826                 }
2827         }
2828
2829  step6:
2830         p = dest;
2831         goto docd;
2832
2833  err:
2834         ash_msg_and_raise_perror("can't cd to %s", dest);
2835         /* NOTREACHED */
2836  out:
2837         if (flags & CD_PRINT)
2838                 out1fmt("%s\n", curdir);
2839         return 0;
2840 }
2841
2842 static int FAST_FUNC
2843 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2844 {
2845         int flags;
2846         const char *dir = curdir;
2847
2848         flags = cdopt();
2849         if (flags) {
2850                 if (physdir == nullstr)
2851                         setpwd(dir, 0);
2852                 dir = physdir;
2853         }
2854         out1fmt("%s\n", dir);
2855         return 0;
2856 }
2857
2858
2859 /* ============ ... */
2860
2861
2862 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2863
2864 /* Syntax classes */
2865 #define CWORD     0             /* character is nothing special */
2866 #define CNL       1             /* newline character */
2867 #define CBACK     2             /* a backslash character */
2868 #define CSQUOTE   3             /* single quote */
2869 #define CDQUOTE   4             /* double quote */
2870 #define CENDQUOTE 5             /* a terminating quote */
2871 #define CBQUOTE   6             /* backwards single quote */
2872 #define CVAR      7             /* a dollar sign */
2873 #define CENDVAR   8             /* a '}' character */
2874 #define CLP       9             /* a left paren in arithmetic */
2875 #define CRP      10             /* a right paren in arithmetic */
2876 #define CENDFILE 11             /* end of file */
2877 #define CCTL     12             /* like CWORD, except it must be escaped */
2878 #define CSPCL    13             /* these terminate a word */
2879 #define CIGN     14             /* character should be ignored */
2880
2881 #define PEOF     256
2882 #if ENABLE_ASH_ALIAS
2883 # define PEOA    257
2884 #endif
2885
2886 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2887
2888 #if ENABLE_FEATURE_SH_MATH
2889 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2890 #else
2891 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2892 #endif
2893 static const uint16_t S_I_T[] ALIGN2 = {
2894 #if ENABLE_ASH_ALIAS
2895         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2896 #endif
2897         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2898         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2899         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2900         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2901         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2902         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2903         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2904         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2905         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2906         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2907         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2908 #if !USE_SIT_FUNCTION
2909         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2910         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2911         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2912 #endif
2913 #undef SIT_ITEM
2914 };
2915 /* Constants below must match table above */
2916 enum {
2917 #if ENABLE_ASH_ALIAS
2918         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2919 #endif
2920         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2921         CNL_CNL_CNL_CNL                    , /*  2 */
2922         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2923         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2924         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2925         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2926         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2927         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2928         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2929         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2930         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2931         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2932         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2933         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2934 };
2935
2936 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2937  * caller must ensure proper cast on it if c is *char_ptr!
2938  */
2939 #if USE_SIT_FUNCTION
2940
2941 static int
2942 SIT(int c, int syntax)
2943 {
2944         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2945         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2946         /*
2947          * This causes '/' to be prepended with CTLESC in dquoted string,
2948          * making "./file"* treated incorrectly because we feed
2949          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2950          * The "homegrown" glob implementation is okay with that,
2951          * but glibc one isn't. With '/' always treated as CWORD,
2952          * both work fine.
2953          */
2954 # if ENABLE_ASH_ALIAS
2955         static const uint8_t syntax_index_table[] ALIGN1 = {
2956                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2957                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2958                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2959                 11, 3                           /* "}~" */
2960         };
2961 # else
2962         static const uint8_t syntax_index_table[] ALIGN1 = {
2963                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2964                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2965                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2966                 10, 2                           /* "}~" */
2967         };
2968 # endif
2969         const char *s;
2970         int indx;
2971
2972         if (c == PEOF)
2973                 return CENDFILE;
2974 # if ENABLE_ASH_ALIAS
2975         if (c == PEOA)
2976                 indx = 0;
2977         else
2978 # endif
2979         {
2980                 /* Cast is purely for paranoia here,
2981                  * just in case someone passed signed char to us */
2982                 if ((unsigned char)c >= CTL_FIRST
2983                  && (unsigned char)c <= CTL_LAST
2984                 ) {
2985                         return CCTL;
2986                 }
2987                 s = strchrnul(spec_symbls, c);
2988                 if (*s == '\0')
2989                         return CWORD;
2990                 indx = syntax_index_table[s - spec_symbls];
2991         }
2992         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2993 }
2994
2995 #else   /* !USE_SIT_FUNCTION */
2996
2997 static const uint8_t syntax_index_table[] ALIGN1 = {
2998         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2999         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3000         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3001         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3002         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3003         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3004         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3005         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3006         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3007         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3008         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3009         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3010         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3011         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3012         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3013         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3014         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3015         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3016         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3017         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3018         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3019         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3020         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3021         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3022         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3023         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3024         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3025         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3029         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3030         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3031         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3032         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3033         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3034         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3035         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3036         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3037         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3038         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3039         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3040         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3041         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3042         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3043         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3044         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3045         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3046 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3047         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3048         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3049         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3050         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3051         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3053         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3054         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3055         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3056         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3057         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3059         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3060         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3061         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3062         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3063         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3064         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3065         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3066         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3067         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3074         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3075         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3076         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3077         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3078         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3089         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3090         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3092         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3093         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3094         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3095         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3096         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3097         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3100         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3101         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3102         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3103         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3104         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3105         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3106         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3107         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3108         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3109         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3110         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3111         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3112         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3113         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3114         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3122         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3123         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3124         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3125         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3126         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3127         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3128         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3129         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3130         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3131         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3132         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3133         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3134         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3135         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3136         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3137         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3256         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3257 # if ENABLE_ASH_ALIAS
3258         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3259 # endif
3260 };
3261
3262 #if 1
3263 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3264 #else /* debug version, caught one signed char bug */
3265 # define SIT(c, syntax) \
3266         ({ \
3267                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3268                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3269                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3270                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3271                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3272         })
3273 #endif
3274
3275 #endif  /* !USE_SIT_FUNCTION */
3276
3277
3278 /* ============ Alias handling */
3279
3280 #if ENABLE_ASH_ALIAS
3281
3282 #define ALIASINUSE 1
3283 #define ALIASDEAD  2
3284
3285 struct alias {
3286         struct alias *next;
3287         char *name;
3288         char *val;
3289         int flag;
3290 };
3291
3292
3293 static struct alias **atab; // [ATABSIZE];
3294 #define INIT_G_alias() do { \
3295         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3296 } while (0)
3297
3298
3299 static struct alias **
3300 __lookupalias(const char *name)
3301 {
3302         unsigned int hashval;
3303         struct alias **app;
3304         const char *p;
3305         unsigned int ch;
3306
3307         p = name;
3308
3309         ch = (unsigned char)*p;
3310         hashval = ch << 4;
3311         while (ch) {
3312                 hashval += ch;
3313                 ch = (unsigned char)*++p;
3314         }
3315         app = &atab[hashval % ATABSIZE];
3316
3317         for (; *app; app = &(*app)->next) {
3318                 if (strcmp(name, (*app)->name) == 0) {
3319                         break;
3320                 }
3321         }
3322
3323         return app;
3324 }
3325
3326 static struct alias *
3327 lookupalias(const char *name, int check)
3328 {
3329         struct alias *ap = *__lookupalias(name);
3330
3331         if (check && ap && (ap->flag & ALIASINUSE))
3332                 return NULL;
3333         return ap;
3334 }
3335
3336 static struct alias *
3337 freealias(struct alias *ap)
3338 {
3339         struct alias *next;
3340
3341         if (ap->flag & ALIASINUSE) {
3342                 ap->flag |= ALIASDEAD;
3343                 return ap;
3344         }
3345
3346         next = ap->next;
3347         free(ap->name);
3348         free(ap->val);
3349         free(ap);
3350         return next;
3351 }
3352
3353 static void
3354 setalias(const char *name, const char *val)
3355 {
3356         struct alias *ap, **app;
3357
3358         app = __lookupalias(name);
3359         ap = *app;
3360         INT_OFF;
3361         if (ap) {
3362                 if (!(ap->flag & ALIASINUSE)) {
3363                         free(ap->val);
3364                 }
3365                 ap->val = ckstrdup(val);
3366                 ap->flag &= ~ALIASDEAD;
3367         } else {
3368                 /* not found */
3369                 ap = ckzalloc(sizeof(struct alias));
3370                 ap->name = ckstrdup(name);
3371                 ap->val = ckstrdup(val);
3372                 /*ap->flag = 0; - ckzalloc did it */
3373                 /*ap->next = NULL;*/
3374                 *app = ap;
3375         }
3376         INT_ON;
3377 }
3378
3379 static int
3380 unalias(const char *name)
3381 {
3382         struct alias **app;
3383
3384         app = __lookupalias(name);
3385
3386         if (*app) {
3387                 INT_OFF;
3388                 *app = freealias(*app);
3389                 INT_ON;
3390                 return 0;
3391         }
3392
3393         return 1;
3394 }
3395
3396 static void
3397 rmaliases(void)
3398 {
3399         struct alias *ap, **app;
3400         int i;
3401
3402         INT_OFF;
3403         for (i = 0; i < ATABSIZE; i++) {
3404                 app = &atab[i];
3405                 for (ap = *app; ap; ap = *app) {
3406                         *app = freealias(*app);
3407                         if (ap == *app) {
3408                                 app = &ap->next;
3409                         }
3410                 }
3411         }
3412         INT_ON;
3413 }
3414
3415 static void
3416 printalias(const struct alias *ap)
3417 {
3418         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3419 }
3420
3421 /*
3422  * TODO - sort output
3423  */
3424 static int FAST_FUNC
3425 aliascmd(int argc UNUSED_PARAM, char **argv)
3426 {
3427         char *n, *v;
3428         int ret = 0;
3429         struct alias *ap;
3430
3431         if (!argv[1]) {
3432                 int i;
3433
3434                 for (i = 0; i < ATABSIZE; i++) {
3435                         for (ap = atab[i]; ap; ap = ap->next) {
3436                                 printalias(ap);
3437                         }
3438                 }
3439                 return 0;
3440         }
3441         while ((n = *++argv) != NULL) {
3442                 v = strchr(n+1, '=');
3443                 if (v == NULL) { /* n+1: funny ksh stuff */
3444                         ap = *__lookupalias(n);
3445                         if (ap == NULL) {
3446                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3447                                 ret = 1;
3448                         } else
3449                                 printalias(ap);
3450                 } else {
3451                         *v++ = '\0';
3452                         setalias(n, v);
3453                 }
3454         }
3455
3456         return ret;
3457 }
3458
3459 static int FAST_FUNC
3460 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3461 {
3462         int i;
3463
3464         while (nextopt("a") != '\0') {
3465                 rmaliases();
3466                 return 0;
3467         }
3468         for (i = 0; *argptr; argptr++) {
3469                 if (unalias(*argptr)) {
3470                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3471                         i = 1;
3472                 }
3473         }
3474
3475         return i;
3476 }
3477
3478 #endif /* ASH_ALIAS */
3479
3480
3481 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3482 #define FORK_FG    0
3483 #define FORK_BG    1
3484 #define FORK_NOJOB 2
3485
3486 /* mode flags for showjob(s) */
3487 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3488 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3489 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3490 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3491
3492 /*
3493  * A job structure contains information about a job.  A job is either a
3494  * single process or a set of processes contained in a pipeline.  In the
3495  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3496  * array of pids.
3497  */
3498 struct procstat {
3499         pid_t   ps_pid;         /* process id */
3500         int     ps_status;      /* last process status from wait() */
3501         char    *ps_cmd;        /* text of command being run */
3502 };
3503
3504 struct job {
3505         struct procstat ps0;    /* status of process */
3506         struct procstat *ps;    /* status or processes when more than one */
3507 #if JOBS
3508         int stopstatus;         /* status of a stopped job */
3509 #endif
3510         unsigned nprocs;        /* number of processes */
3511
3512 #define JOBRUNNING      0       /* at least one proc running */
3513 #define JOBSTOPPED      1       /* all procs are stopped */
3514 #define JOBDONE         2       /* all procs are completed */
3515         unsigned
3516                 state: 8,
3517 #if JOBS
3518                 sigint: 1,      /* job was killed by SIGINT */
3519                 jobctl: 1,      /* job running under job control */
3520 #endif
3521                 waited: 1,      /* true if this entry has been waited for */
3522                 used: 1,        /* true if this entry is in used */
3523                 changed: 1;     /* true if status has changed */
3524         struct job *prev_job;   /* previous job */
3525 };
3526
3527 static struct job *makejob(/*union node *,*/ int);
3528 static int forkshell(struct job *, union node *, int);
3529 static int waitforjob(struct job *);
3530
3531 #if !JOBS
3532 enum { doing_jobctl = 0 };
3533 #define setjobctl(on) do {} while (0)
3534 #else
3535 static smallint doing_jobctl; //references:8
3536 static void setjobctl(int);
3537 #endif
3538
3539 /*
3540  * Ignore a signal.
3541  */
3542 static void
3543 ignoresig(int signo)
3544 {
3545         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3546         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3547                 /* No, need to do it */
3548                 signal(signo, SIG_IGN);
3549         }
3550         sigmode[signo - 1] = S_HARD_IGN;
3551 }
3552
3553 /*
3554  * Only one usage site - in setsignal()
3555  */
3556 static void
3557 signal_handler(int signo)
3558 {
3559         if (signo == SIGCHLD) {
3560                 got_sigchld = 1;
3561                 if (!trap[SIGCHLD])
3562                         return;
3563         }
3564
3565         gotsig[signo - 1] = 1;
3566         pending_sig = signo;
3567
3568         if (signo == SIGINT && !trap[SIGINT]) {
3569                 if (!suppress_int) {
3570                         pending_sig = 0;
3571                         raise_interrupt(); /* does not return */
3572                 }
3573                 pending_int = 1;
3574         }
3575 }
3576
3577 /*
3578  * Set the signal handler for the specified signal.  The routine figures
3579  * out what it should be set to.
3580  */
3581 static void
3582 setsignal(int signo)
3583 {
3584         char *t;
3585         char cur_act, new_act;
3586         struct sigaction act;
3587
3588         t = trap[signo];
3589         new_act = S_DFL;
3590         if (t != NULL) { /* trap for this sig is set */
3591                 new_act = S_CATCH;
3592                 if (t[0] == '\0') /* trap is "": ignore this sig */
3593                         new_act = S_IGN;
3594         }
3595
3596         if (rootshell && new_act == S_DFL) {
3597                 switch (signo) {
3598                 case SIGINT:
3599                         if (iflag || minusc || sflag == 0)
3600                                 new_act = S_CATCH;
3601                         break;
3602                 case SIGQUIT:
3603 #if DEBUG
3604                         if (debug)
3605                                 break;
3606 #endif
3607                         /* man bash:
3608                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3609                          * commands run by bash have signal handlers
3610                          * set to the values inherited by the shell
3611                          * from its parent". */
3612                         new_act = S_IGN;
3613                         break;
3614                 case SIGTERM:
3615                         if (iflag)
3616                                 new_act = S_IGN;
3617                         break;
3618 #if JOBS
3619                 case SIGTSTP:
3620                 case SIGTTOU:
3621                         if (mflag)
3622                                 new_act = S_IGN;
3623                         break;
3624 #endif
3625                 }
3626         }
3627         /* if !rootshell, we reset SIGQUIT to DFL,
3628          * whereas we have to restore it to what shell got on entry.
3629          * This is handled by the fact that if signal was IGNored on entry,
3630          * then cur_act is S_HARD_IGN and we never change its sigaction
3631          * (see code below).
3632          */
3633
3634         if (signo == SIGCHLD)
3635                 new_act = S_CATCH;
3636
3637         t = &sigmode[signo - 1];
3638         cur_act = *t;
3639         if (cur_act == 0) {
3640                 /* current setting is not yet known */
3641                 if (sigaction(signo, NULL, &act)) {
3642                         /* pretend it worked; maybe we should give a warning,
3643                          * but other shells don't. We don't alter sigmode,
3644                          * so we retry every time.
3645                          * btw, in Linux it never fails. --vda */
3646                         return;
3647                 }
3648                 if (act.sa_handler == SIG_IGN) {
3649                         cur_act = S_HARD_IGN;
3650                         if (mflag
3651                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3652                         ) {
3653                                 cur_act = S_IGN;   /* don't hard ignore these */
3654                         }
3655                 }
3656                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3657                         /* installing SIG_DFL over SIG_DFL is a no-op */
3658                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3659                         *t = S_DFL;
3660                         return;
3661                 }
3662         }
3663         if (cur_act == S_HARD_IGN || cur_act == new_act)
3664                 return;
3665
3666         *t = new_act;
3667
3668         act.sa_handler = SIG_DFL;
3669         switch (new_act) {
3670         case S_CATCH:
3671                 act.sa_handler = signal_handler;
3672                 break;
3673         case S_IGN:
3674                 act.sa_handler = SIG_IGN;
3675                 break;
3676         }
3677         /* flags and mask matter only if !DFL and !IGN, but we do it
3678          * for all cases for more deterministic behavior:
3679          */
3680         act.sa_flags = 0; //TODO: why not SA_RESTART?
3681         sigfillset(&act.sa_mask);
3682
3683         sigaction_set(signo, &act);
3684 }
3685
3686 /* mode flags for set_curjob */
3687 #define CUR_DELETE 2
3688 #define CUR_RUNNING 1
3689 #define CUR_STOPPED 0
3690
3691 #if JOBS
3692 /* pgrp of shell on invocation */
3693 static int initialpgrp; //references:2
3694 static int ttyfd = -1; //5
3695 #endif
3696 /* array of jobs */
3697 static struct job *jobtab; //5
3698 /* size of array */
3699 static unsigned njobs; //4
3700 /* current job */
3701 static struct job *curjob; //lots
3702 /* number of presumed living untracked jobs */
3703 static int jobless; //4
3704
3705 #if 0
3706 /* Bash has a feature: it restores termios after a successful wait for
3707  * a foreground job which had at least one stopped or sigkilled member.
3708  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3709  * properly restoring tty state. Should we do this too?
3710  * A reproducer: ^Z an interactive python:
3711  *
3712  * # python
3713  * Python 2.7.12 (...)
3714  * >>> ^Z
3715  *      { python leaves tty in -icanon -echo state. We do survive that... }
3716  *  [1]+  Stopped                    python
3717  *      { ...however, next program (python #2) does not survive it well: }
3718  * # python
3719  * Python 2.7.12 (...)
3720  * >>> Traceback (most recent call last):
3721  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3722  *   File "<stdin>", line 1, in <module>
3723  * NameError: name 'qwerty' is not defined
3724  *
3725  * The implementation below is modeled on bash code and seems to work.
3726  * However, I'm not sure we should do this. For one: what if I'd fg
3727  * the stopped python instead? It'll be confused by "restored" tty state.
3728  */
3729 static struct termios shell_tty_info;
3730 static void
3731 get_tty_state(void)
3732 {
3733         if (rootshell && ttyfd >= 0)
3734                 tcgetattr(ttyfd, &shell_tty_info);
3735 }
3736 static void
3737 set_tty_state(void)
3738 {
3739         /* if (rootshell) - caller ensures this */
3740         if (ttyfd >= 0)
3741                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3742 }
3743 static int
3744 job_signal_status(struct job *jp)
3745 {
3746         int status;
3747         unsigned i;
3748         struct procstat *ps = jp->ps;
3749         for (i = 0; i < jp->nprocs; i++) {
3750                 status = ps[i].ps_status;
3751                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3752                         return status;
3753         }
3754         return 0;
3755 }
3756 static void
3757 restore_tty_if_stopped_or_signaled(struct job *jp)
3758 {
3759 //TODO: check what happens if we come from waitforjob() in expbackq()
3760         if (rootshell) {
3761                 int s = job_signal_status(jp);
3762                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3763                         set_tty_state();
3764         }
3765 }
3766 #else
3767 # define get_tty_state() ((void)0)
3768 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3769 #endif
3770
3771 static void
3772 set_curjob(struct job *jp, unsigned mode)
3773 {
3774         struct job *jp1;
3775         struct job **jpp, **curp;
3776
3777         /* first remove from list */
3778         jpp = curp = &curjob;
3779         while (1) {
3780                 jp1 = *jpp;
3781                 if (jp1 == jp)
3782                         break;
3783                 jpp = &jp1->prev_job;
3784         }
3785         *jpp = jp1->prev_job;
3786
3787         /* Then re-insert in correct position */
3788         jpp = curp;
3789         switch (mode) {
3790         default:
3791 #if DEBUG
3792                 abort();
3793 #endif
3794         case CUR_DELETE:
3795                 /* job being deleted */
3796                 break;
3797         case CUR_RUNNING:
3798                 /* newly created job or backgrounded job,
3799                  * put after all stopped jobs.
3800                  */
3801                 while (1) {
3802                         jp1 = *jpp;
3803 #if JOBS
3804                         if (!jp1 || jp1->state != JOBSTOPPED)
3805 #endif
3806                                 break;
3807                         jpp = &jp1->prev_job;
3808                 }
3809                 /* FALLTHROUGH */
3810 #if JOBS
3811         case CUR_STOPPED:
3812 #endif
3813                 /* newly stopped job - becomes curjob */
3814                 jp->prev_job = *jpp;
3815                 *jpp = jp;
3816                 break;
3817         }
3818 }
3819
3820 #if JOBS || DEBUG
3821 static int
3822 jobno(const struct job *jp)
3823 {
3824         return jp - jobtab + 1;
3825 }
3826 #endif
3827
3828 /*
3829  * Convert a job name to a job structure.
3830  */
3831 #if !JOBS
3832 #define getjob(name, getctl) getjob(name)
3833 #endif
3834 static struct job *
3835 getjob(const char *name, int getctl)
3836 {
3837         struct job *jp;
3838         struct job *found;
3839         const char *err_msg = "%s: no such job";
3840         unsigned num;
3841         int c;
3842         const char *p;
3843         char *(*match)(const char *, const char *);
3844
3845         jp = curjob;
3846         p = name;
3847         if (!p)
3848                 goto currentjob;
3849
3850         if (*p != '%')
3851                 goto err;
3852
3853         c = *++p;
3854         if (!c)
3855                 goto currentjob;
3856
3857         if (!p[1]) {
3858                 if (c == '+' || c == '%') {
3859  currentjob:
3860                         err_msg = "No current job";
3861                         goto check;
3862                 }
3863                 if (c == '-') {
3864                         if (jp)
3865                                 jp = jp->prev_job;
3866                         err_msg = "No previous job";
3867  check:
3868                         if (!jp)
3869                                 goto err;
3870                         goto gotit;
3871                 }
3872         }
3873
3874         if (is_number(p)) {
3875                 num = atoi(p);
3876                 if (num > 0 && num <= njobs) {
3877                         jp = jobtab + num - 1;
3878                         if (jp->used)
3879                                 goto gotit;
3880                         goto err;
3881                 }
3882         }
3883
3884         match = prefix;
3885         if (*p == '?') {
3886                 match = strstr;
3887                 p++;
3888         }
3889
3890         found = NULL;
3891         while (jp) {
3892                 if (match(jp->ps[0].ps_cmd, p)) {
3893                         if (found)
3894                                 goto err;
3895                         found = jp;
3896                         err_msg = "%s: ambiguous";
3897                 }
3898                 jp = jp->prev_job;
3899         }
3900         if (!found)
3901                 goto err;
3902         jp = found;
3903
3904  gotit:
3905 #if JOBS
3906         err_msg = "job %s not created under job control";
3907         if (getctl && jp->jobctl == 0)
3908                 goto err;
3909 #endif
3910         return jp;
3911  err:
3912         ash_msg_and_raise_error(err_msg, name);
3913 }
3914
3915 /*
3916  * Mark a job structure as unused.
3917  */
3918 static void
3919 freejob(struct job *jp)
3920 {
3921         struct procstat *ps;
3922         int i;
3923
3924         INT_OFF;
3925         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3926                 if (ps->ps_cmd != nullstr)
3927                         free(ps->ps_cmd);
3928         }
3929         if (jp->ps != &jp->ps0)
3930                 free(jp->ps);
3931         jp->used = 0;
3932         set_curjob(jp, CUR_DELETE);
3933         INT_ON;
3934 }
3935
3936 #if JOBS
3937 static void
3938 xtcsetpgrp(int fd, pid_t pgrp)
3939 {
3940         if (tcsetpgrp(fd, pgrp))
3941                 ash_msg_and_raise_perror("can't set tty process group");
3942 }
3943
3944 /*
3945  * Turn job control on and off.
3946  *
3947  * Note:  This code assumes that the third arg to ioctl is a character
3948  * pointer, which is true on Berkeley systems but not System V.  Since
3949  * System V doesn't have job control yet, this isn't a problem now.
3950  *
3951  * Called with interrupts off.
3952  */
3953 static void
3954 setjobctl(int on)
3955 {
3956         int fd;
3957         int pgrp;
3958
3959         if (on == doing_jobctl || rootshell == 0)
3960                 return;
3961         if (on) {
3962                 int ofd;
3963                 ofd = fd = open(_PATH_TTY, O_RDWR);
3964                 if (fd < 0) {
3965         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3966          * That sometimes helps to acquire controlling tty.
3967          * Obviously, a workaround for bugs when someone
3968          * failed to provide a controlling tty to bash! :) */
3969                         fd = 2;
3970                         while (!isatty(fd))
3971                                 if (--fd < 0)
3972                                         goto out;
3973                 }
3974                 /* fd is a tty at this point */
3975                 fd = fcntl(fd, F_DUPFD, 10);
3976                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3977                         close(ofd);
3978                 if (fd < 0)
3979                         goto out; /* F_DUPFD failed */
3980                 close_on_exec_on(fd);
3981                 while (1) { /* while we are in the background */
3982                         pgrp = tcgetpgrp(fd);
3983                         if (pgrp < 0) {
3984  out:
3985                                 ash_msg("can't access tty; job control turned off");
3986                                 mflag = on = 0;
3987                                 goto close;
3988                         }
3989                         if (pgrp == getpgrp())
3990                                 break;
3991                         killpg(0, SIGTTIN);
3992                 }
3993                 initialpgrp = pgrp;
3994
3995                 setsignal(SIGTSTP);
3996                 setsignal(SIGTTOU);
3997                 setsignal(SIGTTIN);
3998                 pgrp = rootpid;
3999                 setpgid(0, pgrp);
4000                 xtcsetpgrp(fd, pgrp);
4001         } else {
4002                 /* turning job control off */
4003                 fd = ttyfd;
4004                 pgrp = initialpgrp;
4005                 /* was xtcsetpgrp, but this can make exiting ash
4006                  * loop forever if pty is already deleted */
4007                 tcsetpgrp(fd, pgrp);
4008                 setpgid(0, pgrp);
4009                 setsignal(SIGTSTP);
4010                 setsignal(SIGTTOU);
4011                 setsignal(SIGTTIN);
4012  close:
4013                 if (fd >= 0)
4014                         close(fd);
4015                 fd = -1;
4016         }
4017         ttyfd = fd;
4018         doing_jobctl = on;
4019 }
4020
4021 static int FAST_FUNC
4022 killcmd(int argc, char **argv)
4023 {
4024         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4025                 int i = 1;
4026                 do {
4027                         if (argv[i][0] == '%') {
4028                                 /*
4029                                  * "kill %N" - job kill
4030                                  * Converting to pgrp / pid kill
4031                                  */
4032                                 struct job *jp;
4033                                 char *dst;
4034                                 int j, n;
4035
4036                                 jp = getjob(argv[i], 0);
4037                                 /*
4038                                  * In jobs started under job control, we signal
4039                                  * entire process group by kill -PGRP_ID.
4040                                  * This happens, f.e., in interactive shell.
4041                                  *
4042                                  * Otherwise, we signal each child via
4043                                  * kill PID1 PID2 PID3.
4044                                  * Testcases:
4045                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4046                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4047                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4048                                  */
4049                                 n = jp->nprocs; /* can't be 0 (I hope) */
4050                                 if (jp->jobctl)
4051                                         n = 1;
4052                                 dst = alloca(n * sizeof(int)*4);
4053                                 argv[i] = dst;
4054                                 for (j = 0; j < n; j++) {
4055                                         struct procstat *ps = &jp->ps[j];
4056                                         /* Skip non-running and not-stopped members
4057                                          * (i.e. dead members) of the job
4058                                          */
4059                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4060                                                 continue;
4061                                         /*
4062                                          * kill_main has matching code to expect
4063                                          * leading space. Needed to not confuse
4064                                          * negative pids with "kill -SIGNAL_NO" syntax
4065                                          */
4066                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4067                                 }
4068                                 *dst = '\0';
4069                         }
4070                 } while (argv[++i]);
4071         }
4072         return kill_main(argc, argv);
4073 }
4074
4075 static void
4076 showpipe(struct job *jp /*, FILE *out*/)
4077 {
4078         struct procstat *ps;
4079         struct procstat *psend;
4080
4081         psend = jp->ps + jp->nprocs;
4082         for (ps = jp->ps + 1; ps < psend; ps++)
4083                 printf(" | %s", ps->ps_cmd);
4084         newline_and_flush(stdout);
4085         flush_stdout_stderr();
4086 }
4087
4088
4089 static int
4090 restartjob(struct job *jp, int mode)
4091 {
4092         struct procstat *ps;
4093         int i;
4094         int status;
4095         pid_t pgid;
4096
4097         INT_OFF;
4098         if (jp->state == JOBDONE)
4099                 goto out;
4100         jp->state = JOBRUNNING;
4101         pgid = jp->ps[0].ps_pid;
4102         if (mode == FORK_FG) {
4103                 get_tty_state();
4104                 xtcsetpgrp(ttyfd, pgid);
4105         }
4106         killpg(pgid, SIGCONT);
4107         ps = jp->ps;
4108         i = jp->nprocs;
4109         do {
4110                 if (WIFSTOPPED(ps->ps_status)) {
4111                         ps->ps_status = -1;
4112                 }
4113                 ps++;
4114         } while (--i);
4115  out:
4116         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4117         INT_ON;
4118         return status;
4119 }
4120
4121 static int FAST_FUNC
4122 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4123 {
4124         struct job *jp;
4125         int mode;
4126         int retval;
4127
4128         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4129         nextopt(nullstr);
4130         argv = argptr;
4131         do {
4132                 jp = getjob(*argv, 1);
4133                 if (mode == FORK_BG) {
4134                         set_curjob(jp, CUR_RUNNING);
4135                         printf("[%d] ", jobno(jp));
4136                 }
4137                 out1str(jp->ps[0].ps_cmd);
4138                 showpipe(jp /*, stdout*/);
4139                 retval = restartjob(jp, mode);
4140         } while (*argv && *++argv);
4141         return retval;
4142 }
4143 #endif
4144
4145 static int
4146 sprint_status48(char *s, int status, int sigonly)
4147 {
4148         int col;
4149         int st;
4150
4151         col = 0;
4152         if (!WIFEXITED(status)) {
4153 #if JOBS
4154                 if (WIFSTOPPED(status))
4155                         st = WSTOPSIG(status);
4156                 else
4157 #endif
4158                         st = WTERMSIG(status);
4159                 if (sigonly) {
4160                         if (st == SIGINT || st == SIGPIPE)
4161                                 goto out;
4162 #if JOBS
4163                         if (WIFSTOPPED(status))
4164                                 goto out;
4165 #endif
4166                 }
4167                 st &= 0x7f;
4168 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4169                 col = fmtstr(s, 32, strsignal(st));
4170                 if (WCOREDUMP(status)) {
4171                         strcpy(s + col, " (core dumped)");
4172                         col += sizeof(" (core dumped)")-1;
4173                 }
4174         } else if (!sigonly) {
4175                 st = WEXITSTATUS(status);
4176                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4177         }
4178  out:
4179         return col;
4180 }
4181
4182 static int
4183 wait_block_or_sig(int *status)
4184 {
4185         int pid;
4186
4187         do {
4188                 sigset_t mask;
4189
4190                 /* Poll all children for changes in their state */
4191                 got_sigchld = 0;
4192                 /* if job control is active, accept stopped processes too */
4193                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4194                 if (pid != 0)
4195                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4196
4197                 /* Children exist, but none are ready. Sleep until interesting signal */
4198 #if 1
4199                 sigfillset(&mask);
4200                 sigprocmask(SIG_SETMASK, &mask, &mask);
4201                 while (!got_sigchld && !pending_sig)
4202                         sigsuspend(&mask);
4203                 sigprocmask(SIG_SETMASK, &mask, NULL);
4204 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4205                 while (!got_sigchld && !pending_sig)
4206                         pause();
4207 #endif
4208
4209                 /* If it was SIGCHLD, poll children again */
4210         } while (got_sigchld);
4211
4212         return pid;
4213 }
4214
4215 #define DOWAIT_NONBLOCK 0
4216 #define DOWAIT_BLOCK    1
4217 #define DOWAIT_BLOCK_OR_SIG 2
4218
4219 static int
4220 dowait(int block, struct job *job)
4221 {
4222         int pid;
4223         int status;
4224         struct job *jp;
4225         struct job *thisjob = NULL;
4226
4227         TRACE(("dowait(0x%x) called\n", block));
4228
4229         /* It's wrong to call waitpid() outside of INT_OFF region:
4230          * signal can arrive just after syscall return and handler can
4231          * longjmp away, losing stop/exit notification processing.
4232          * Thus, for "jobs" builtin, and for waiting for a fg job,
4233          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4234          *
4235          * However, for "wait" builtin it is wrong to simply call waitpid()
4236          * in INT_OFF region: "wait" needs to wait for any running job
4237          * to change state, but should exit on any trap too.
4238          * In INT_OFF region, a signal just before syscall entry can set
4239          * pending_sig variables, but we can't check them, and we would
4240          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4241          *
4242          * Because of this, we run inside INT_OFF, but use a special routine
4243          * which combines waitpid() and sigsuspend().
4244          * This is the reason why we need to have a handler for SIGCHLD:
4245          * SIG_DFL handler does not wake sigsuspend().
4246          */
4247         INT_OFF;
4248         if (block == DOWAIT_BLOCK_OR_SIG) {
4249                 pid = wait_block_or_sig(&status);
4250         } else {
4251                 int wait_flags = 0;
4252                 if (block == DOWAIT_NONBLOCK)
4253                         wait_flags = WNOHANG;
4254                 /* if job control is active, accept stopped processes too */
4255                 if (doing_jobctl)
4256                         wait_flags |= WUNTRACED;
4257                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4258                 pid = waitpid(-1, &status, wait_flags);
4259         }
4260         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4261                                 pid, status, errno, strerror(errno)));
4262         if (pid <= 0)
4263                 goto out;
4264
4265         thisjob = NULL;
4266         for (jp = curjob; jp; jp = jp->prev_job) {
4267                 int jobstate;
4268                 struct procstat *ps;
4269                 struct procstat *psend;
4270                 if (jp->state == JOBDONE)
4271                         continue;
4272                 jobstate = JOBDONE;
4273                 ps = jp->ps;
4274                 psend = ps + jp->nprocs;
4275                 do {
4276                         if (ps->ps_pid == pid) {
4277                                 TRACE(("Job %d: changing status of proc %d "
4278                                         "from 0x%x to 0x%x\n",
4279                                         jobno(jp), pid, ps->ps_status, status));
4280                                 ps->ps_status = status;
4281                                 thisjob = jp;
4282                         }
4283                         if (ps->ps_status == -1)
4284                                 jobstate = JOBRUNNING;
4285 #if JOBS
4286                         if (jobstate == JOBRUNNING)
4287                                 continue;
4288                         if (WIFSTOPPED(ps->ps_status)) {
4289                                 jp->stopstatus = ps->ps_status;
4290                                 jobstate = JOBSTOPPED;
4291                         }
4292 #endif
4293                 } while (++ps < psend);
4294                 if (!thisjob)
4295                         continue;
4296
4297                 /* Found the job where one of its processes changed its state.
4298                  * Is there at least one live and running process in this job? */
4299                 if (jobstate != JOBRUNNING) {
4300                         /* No. All live processes in the job are stopped
4301                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4302                          */
4303                         thisjob->changed = 1;
4304                         if (thisjob->state != jobstate) {
4305                                 TRACE(("Job %d: changing state from %d to %d\n",
4306                                         jobno(thisjob), thisjob->state, jobstate));
4307                                 thisjob->state = jobstate;
4308 #if JOBS
4309                                 if (jobstate == JOBSTOPPED)
4310                                         set_curjob(thisjob, CUR_STOPPED);
4311 #endif
4312                         }
4313                 }
4314                 goto out;
4315         }
4316         /* The process wasn't found in job list */
4317 #if JOBS
4318         if (!WIFSTOPPED(status))
4319                 jobless--;
4320 #endif
4321  out:
4322         INT_ON;
4323
4324         if (thisjob && thisjob == job) {
4325                 char s[48 + 1];
4326                 int len;
4327
4328                 len = sprint_status48(s, status, 1);
4329                 if (len) {
4330                         s[len] = '\n';
4331                         s[len + 1] = '\0';
4332                         out2str(s);
4333                 }
4334         }
4335         return pid;
4336 }
4337
4338 #if JOBS
4339 static void
4340 showjob(struct job *jp, int mode)
4341 {
4342         struct procstat *ps;
4343         struct procstat *psend;
4344         int col;
4345         int indent_col;
4346         char s[16 + 16 + 48];
4347         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4348
4349         ps = jp->ps;
4350
4351         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4352                 /* just output process (group) id of pipeline */
4353                 fprintf(out, "%d\n", ps->ps_pid);
4354                 return;
4355         }
4356
4357         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4358         indent_col = col;
4359
4360         if (jp == curjob)
4361                 s[col - 3] = '+';
4362         else if (curjob && jp == curjob->prev_job)
4363                 s[col - 3] = '-';
4364
4365         if (mode & SHOW_PIDS)
4366                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4367
4368         psend = ps + jp->nprocs;
4369
4370         if (jp->state == JOBRUNNING) {
4371                 strcpy(s + col, "Running");
4372                 col += sizeof("Running") - 1;
4373         } else {
4374                 int status = psend[-1].ps_status;
4375                 if (jp->state == JOBSTOPPED)
4376                         status = jp->stopstatus;
4377                 col += sprint_status48(s + col, status, 0);
4378         }
4379         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4380
4381         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4382          * or prints several "PID             | <cmdN>" lines,
4383          * depending on SHOW_PIDS bit.
4384          * We do not print status of individual processes
4385          * between PID and <cmdN>. bash does it, but not very well:
4386          * first line shows overall job status, not process status,
4387          * making it impossible to know 1st process status.
4388          */
4389         goto start;
4390         do {
4391                 /* for each process */
4392                 s[0] = '\0';
4393                 col = 33;
4394                 if (mode & SHOW_PIDS)
4395                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4396  start:
4397                 fprintf(out, "%s%*c%s%s",
4398                                 s,
4399                                 33 - col >= 0 ? 33 - col : 0, ' ',
4400                                 ps == jp->ps ? "" : "| ",
4401                                 ps->ps_cmd
4402                 );
4403         } while (++ps != psend);
4404         newline_and_flush(out);
4405
4406         jp->changed = 0;
4407
4408         if (jp->state == JOBDONE) {
4409                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4410                 freejob(jp);
4411         }
4412 }
4413
4414 /*
4415  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4416  * statuses have changed since the last call to showjobs.
4417  */
4418 static void
4419 showjobs(int mode)
4420 {
4421         struct job *jp;
4422
4423         TRACE(("showjobs(0x%x) called\n", mode));
4424
4425         /* Handle all finished jobs */
4426         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4427                 continue;
4428
4429         for (jp = curjob; jp; jp = jp->prev_job) {
4430                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4431                         showjob(jp, mode);
4432                 }
4433         }
4434 }
4435
4436 static int FAST_FUNC
4437 jobscmd(int argc UNUSED_PARAM, char **argv)
4438 {
4439         int mode, m;
4440
4441         mode = 0;
4442         while ((m = nextopt("lp")) != '\0') {
4443                 if (m == 'l')
4444                         mode |= SHOW_PIDS;
4445                 else
4446                         mode |= SHOW_ONLY_PGID;
4447         }
4448
4449         argv = argptr;
4450         if (*argv) {
4451                 do
4452                         showjob(getjob(*argv, 0), mode);
4453                 while (*++argv);
4454         } else {
4455                 showjobs(mode);
4456         }
4457
4458         return 0;
4459 }
4460 #endif /* JOBS */
4461
4462 /* Called only on finished or stopped jobs (no members are running) */
4463 static int
4464 getstatus(struct job *job)
4465 {
4466         int status;
4467         int retval;
4468         struct procstat *ps;
4469
4470         /* Fetch last member's status */
4471         ps = job->ps + job->nprocs - 1;
4472         status = ps->ps_status;
4473         if (pipefail) {
4474                 /* "set -o pipefail" mode: use last _nonzero_ status */
4475                 while (status == 0 && --ps >= job->ps)
4476                         status = ps->ps_status;
4477         }
4478
4479         retval = WEXITSTATUS(status);
4480         if (!WIFEXITED(status)) {
4481 #if JOBS
4482                 retval = WSTOPSIG(status);
4483                 if (!WIFSTOPPED(status))
4484 #endif
4485                 {
4486                         /* XXX: limits number of signals */
4487                         retval = WTERMSIG(status);
4488 #if JOBS
4489                         if (retval == SIGINT)
4490                                 job->sigint = 1;
4491 #endif
4492                 }
4493                 retval += 128;
4494         }
4495         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4496                 jobno(job), job->nprocs, status, retval));
4497         return retval;
4498 }
4499
4500 static int FAST_FUNC
4501 waitcmd(int argc UNUSED_PARAM, char **argv)
4502 {
4503         struct job *job;
4504         int retval;
4505         struct job *jp;
4506
4507         nextopt(nullstr);
4508         retval = 0;
4509
4510         argv = argptr;
4511         if (!*argv) {
4512                 /* wait for all jobs */
4513                 for (;;) {
4514                         jp = curjob;
4515                         while (1) {
4516                                 if (!jp) /* no running procs */
4517                                         goto ret;
4518                                 if (jp->state == JOBRUNNING)
4519                                         break;
4520                                 jp->waited = 1;
4521                                 jp = jp->prev_job;
4522                         }
4523         /* man bash:
4524          * "When bash is waiting for an asynchronous command via
4525          * the wait builtin, the reception of a signal for which a trap
4526          * has been set will cause the wait builtin to return immediately
4527          * with an exit status greater than 128, immediately after which
4528          * the trap is executed."
4529          */
4530                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4531         /* if child sends us a signal *and immediately exits*,
4532          * dowait() returns pid > 0. Check this case,
4533          * not "if (dowait() < 0)"!
4534          */
4535                         if (pending_sig)
4536                                 goto sigout;
4537                 }
4538         }
4539
4540         retval = 127;
4541         do {
4542                 if (**argv != '%') {
4543                         pid_t pid = number(*argv);
4544                         job = curjob;
4545                         while (1) {
4546                                 if (!job)
4547                                         goto repeat;
4548                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4549                                         break;
4550                                 job = job->prev_job;
4551                         }
4552                 } else {
4553                         job = getjob(*argv, 0);
4554                 }
4555                 /* loop until process terminated or stopped */
4556                 while (job->state == JOBRUNNING) {
4557                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4558                         if (pending_sig)
4559                                 goto sigout;
4560                 }
4561                 job->waited = 1;
4562                 retval = getstatus(job);
4563  repeat: ;
4564         } while (*++argv);
4565
4566  ret:
4567         return retval;
4568  sigout:
4569         retval = 128 + pending_sig;
4570         return retval;
4571 }
4572
4573 static struct job *
4574 growjobtab(void)
4575 {
4576         size_t len;
4577         ptrdiff_t offset;
4578         struct job *jp, *jq;
4579
4580         len = njobs * sizeof(*jp);
4581         jq = jobtab;
4582         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4583
4584         offset = (char *)jp - (char *)jq;
4585         if (offset) {
4586                 /* Relocate pointers */
4587                 size_t l = len;
4588
4589                 jq = (struct job *)((char *)jq + l);
4590                 while (l) {
4591                         l -= sizeof(*jp);
4592                         jq--;
4593 #define joff(p) ((struct job *)((char *)(p) + l))
4594 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4595                         if (joff(jp)->ps == &jq->ps0)
4596                                 jmove(joff(jp)->ps);
4597                         if (joff(jp)->prev_job)
4598                                 jmove(joff(jp)->prev_job);
4599                 }
4600                 if (curjob)
4601                         jmove(curjob);
4602 #undef joff
4603 #undef jmove
4604         }
4605
4606         njobs += 4;
4607         jobtab = jp;
4608         jp = (struct job *)((char *)jp + len);
4609         jq = jp + 3;
4610         do {
4611                 jq->used = 0;
4612         } while (--jq >= jp);
4613         return jp;
4614 }
4615
4616 /*
4617  * Return a new job structure.
4618  * Called with interrupts off.
4619  */
4620 static struct job *
4621 makejob(/*union node *node,*/ int nprocs)
4622 {
4623         int i;
4624         struct job *jp;
4625
4626         for (i = njobs, jp = jobtab; ; jp++) {
4627                 if (--i < 0) {
4628                         jp = growjobtab();
4629                         break;
4630                 }
4631                 if (jp->used == 0)
4632                         break;
4633                 if (jp->state != JOBDONE || !jp->waited)
4634                         continue;
4635 #if JOBS
4636                 if (doing_jobctl)
4637                         continue;
4638 #endif
4639                 freejob(jp);
4640                 break;
4641         }
4642         memset(jp, 0, sizeof(*jp));
4643 #if JOBS
4644         /* jp->jobctl is a bitfield.
4645          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4646         if (doing_jobctl)
4647                 jp->jobctl = 1;
4648 #endif
4649         jp->prev_job = curjob;
4650         curjob = jp;
4651         jp->used = 1;
4652         jp->ps = &jp->ps0;
4653         if (nprocs > 1) {
4654                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4655         }
4656         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4657                                 jobno(jp)));
4658         return jp;
4659 }
4660
4661 #if JOBS
4662 /*
4663  * Return a string identifying a command (to be printed by the
4664  * jobs command).
4665  */
4666 static char *cmdnextc;
4667
4668 static void
4669 cmdputs(const char *s)
4670 {
4671         static const char vstype[VSTYPE + 1][3] = {
4672                 "", "}", "-", "+", "?", "=",
4673                 "%", "%%", "#", "##"
4674                 IF_BASH_SUBSTR(, ":")
4675                 IF_BASH_PATTERN_SUBST(, "/", "//")
4676         };
4677
4678         const char *p, *str;
4679         char cc[2];
4680         char *nextc;
4681         unsigned char c;
4682         unsigned char subtype = 0;
4683         int quoted = 0;
4684
4685         cc[1] = '\0';
4686         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4687         p = s;
4688         while ((c = *p++) != '\0') {
4689                 str = NULL;
4690                 switch (c) {
4691                 case CTLESC:
4692                         c = *p++;
4693                         break;
4694                 case CTLVAR:
4695                         subtype = *p++;
4696                         if ((subtype & VSTYPE) == VSLENGTH)
4697                                 str = "${#";
4698                         else
4699                                 str = "${";
4700                         goto dostr;
4701                 case CTLENDVAR:
4702                         str = "\"}" + !(quoted & 1);
4703                         quoted >>= 1;
4704                         subtype = 0;
4705                         goto dostr;
4706                 case CTLBACKQ:
4707                         str = "$(...)";
4708                         goto dostr;
4709 #if ENABLE_FEATURE_SH_MATH
4710                 case CTLARI:
4711                         str = "$((";
4712                         goto dostr;
4713                 case CTLENDARI:
4714                         str = "))";
4715                         goto dostr;
4716 #endif
4717                 case CTLQUOTEMARK:
4718                         quoted ^= 1;
4719                         c = '"';
4720                         break;
4721                 case '=':
4722                         if (subtype == 0)
4723                                 break;
4724                         if ((subtype & VSTYPE) != VSNORMAL)
4725                                 quoted <<= 1;
4726                         str = vstype[subtype & VSTYPE];
4727                         if (subtype & VSNUL)
4728                                 c = ':';
4729                         else
4730                                 goto checkstr;
4731                         break;
4732                 case '\'':
4733                 case '\\':
4734                 case '"':
4735                 case '$':
4736                         /* These can only happen inside quotes */
4737                         cc[0] = c;
4738                         str = cc;
4739 //FIXME:
4740 // $ true $$ &
4741 // $ <cr>
4742 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4743                         c = '\\';
4744                         break;
4745                 default:
4746                         break;
4747                 }
4748                 USTPUTC(c, nextc);
4749  checkstr:
4750                 if (!str)
4751                         continue;
4752  dostr:
4753                 while ((c = *str++) != '\0') {
4754                         USTPUTC(c, nextc);
4755                 }
4756         } /* while *p++ not NUL */
4757
4758         if (quoted & 1) {
4759                 USTPUTC('"', nextc);
4760         }
4761         *nextc = 0;
4762         cmdnextc = nextc;
4763 }
4764
4765 /* cmdtxt() and cmdlist() call each other */
4766 static void cmdtxt(union node *n);
4767
4768 static void
4769 cmdlist(union node *np, int sep)
4770 {
4771         for (; np; np = np->narg.next) {
4772                 if (!sep)
4773                         cmdputs(" ");
4774                 cmdtxt(np);
4775                 if (sep && np->narg.next)
4776                         cmdputs(" ");
4777         }
4778 }
4779
4780 static void
4781 cmdtxt(union node *n)
4782 {
4783         union node *np;
4784         struct nodelist *lp;
4785         const char *p;
4786
4787         if (!n)
4788                 return;
4789         switch (n->type) {
4790         default:
4791 #if DEBUG
4792                 abort();
4793 #endif
4794         case NPIPE:
4795                 lp = n->npipe.cmdlist;
4796                 for (;;) {
4797                         cmdtxt(lp->n);
4798                         lp = lp->next;
4799                         if (!lp)
4800                                 break;
4801                         cmdputs(" | ");
4802                 }
4803                 break;
4804         case NSEMI:
4805                 p = "; ";
4806                 goto binop;
4807         case NAND:
4808                 p = " && ";
4809                 goto binop;
4810         case NOR:
4811                 p = " || ";
4812  binop:
4813                 cmdtxt(n->nbinary.ch1);
4814                 cmdputs(p);
4815                 n = n->nbinary.ch2;
4816                 goto donode;
4817         case NREDIR:
4818         case NBACKGND:
4819                 n = n->nredir.n;
4820                 goto donode;
4821         case NNOT:
4822                 cmdputs("!");
4823                 n = n->nnot.com;
4824  donode:
4825                 cmdtxt(n);
4826                 break;
4827         case NIF:
4828                 cmdputs("if ");
4829                 cmdtxt(n->nif.test);
4830                 cmdputs("; then ");
4831                 if (n->nif.elsepart) {
4832                         cmdtxt(n->nif.ifpart);
4833                         cmdputs("; else ");
4834                         n = n->nif.elsepart;
4835                 } else {
4836                         n = n->nif.ifpart;
4837                 }
4838                 p = "; fi";
4839                 goto dotail;
4840         case NSUBSHELL:
4841                 cmdputs("(");
4842                 n = n->nredir.n;
4843                 p = ")";
4844                 goto dotail;
4845         case NWHILE:
4846                 p = "while ";
4847                 goto until;
4848         case NUNTIL:
4849                 p = "until ";
4850  until:
4851                 cmdputs(p);
4852                 cmdtxt(n->nbinary.ch1);
4853                 n = n->nbinary.ch2;
4854                 p = "; done";
4855  dodo:
4856                 cmdputs("; do ");
4857  dotail:
4858                 cmdtxt(n);
4859                 goto dotail2;
4860         case NFOR:
4861                 cmdputs("for ");
4862                 cmdputs(n->nfor.var);
4863                 cmdputs(" in ");
4864                 cmdlist(n->nfor.args, 1);
4865                 n = n->nfor.body;
4866                 p = "; done";
4867                 goto dodo;
4868         case NDEFUN:
4869                 cmdputs(n->ndefun.text);
4870                 p = "() { ... }";
4871                 goto dotail2;
4872         case NCMD:
4873                 cmdlist(n->ncmd.args, 1);
4874                 cmdlist(n->ncmd.redirect, 0);
4875                 break;
4876         case NARG:
4877                 p = n->narg.text;
4878  dotail2:
4879                 cmdputs(p);
4880                 break;
4881         case NHERE:
4882         case NXHERE:
4883                 p = "<<...";
4884                 goto dotail2;
4885         case NCASE:
4886                 cmdputs("case ");
4887                 cmdputs(n->ncase.expr->narg.text);
4888                 cmdputs(" in ");
4889                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4890                         cmdtxt(np->nclist.pattern);
4891                         cmdputs(") ");
4892                         cmdtxt(np->nclist.body);
4893                         cmdputs(";; ");
4894                 }
4895                 p = "esac";
4896                 goto dotail2;
4897         case NTO:
4898                 p = ">";
4899                 goto redir;
4900         case NCLOBBER:
4901                 p = ">|";
4902                 goto redir;
4903         case NAPPEND:
4904                 p = ">>";
4905                 goto redir;
4906 #if BASH_REDIR_OUTPUT
4907         case NTO2:
4908 #endif
4909         case NTOFD:
4910                 p = ">&";
4911                 goto redir;
4912         case NFROM:
4913                 p = "<";
4914                 goto redir;
4915         case NFROMFD:
4916                 p = "<&";
4917                 goto redir;
4918         case NFROMTO:
4919                 p = "<>";
4920  redir:
4921                 cmdputs(utoa(n->nfile.fd));
4922                 cmdputs(p);
4923                 if (n->type == NTOFD || n->type == NFROMFD) {
4924                         if (n->ndup.dupfd >= 0)
4925                                 cmdputs(utoa(n->ndup.dupfd));
4926                         else
4927                                 cmdputs("-");
4928                         break;
4929                 }
4930                 n = n->nfile.fname;
4931                 goto donode;
4932         }
4933 }
4934
4935 static char *
4936 commandtext(union node *n)
4937 {
4938         char *name;
4939
4940         STARTSTACKSTR(cmdnextc);
4941         cmdtxt(n);
4942         name = stackblock();
4943         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4944         return ckstrdup(name);
4945 }
4946 #endif /* JOBS */
4947
4948 /*
4949  * Fork off a subshell.  If we are doing job control, give the subshell its
4950  * own process group.  Jp is a job structure that the job is to be added to.
4951  * N is the command that will be evaluated by the child.  Both jp and n may
4952  * be NULL.  The mode parameter can be one of the following:
4953  *      FORK_FG - Fork off a foreground process.
4954  *      FORK_BG - Fork off a background process.
4955  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4956  *                   process group even if job control is on.
4957  *
4958  * When job control is turned off, background processes have their standard
4959  * input redirected to /dev/null (except for the second and later processes
4960  * in a pipeline).
4961  *
4962  * Called with interrupts off.
4963  */
4964 /*
4965  * Clear traps on a fork.
4966  */
4967 static void
4968 clear_traps(void)
4969 {
4970         char **tp;
4971
4972         INT_OFF;
4973         for (tp = trap; tp < &trap[NSIG]; tp++) {
4974                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4975                         if (trap_ptr == trap)
4976                                 free(*tp);
4977                         /* else: it "belongs" to trap_ptr vector, don't free */
4978                         *tp = NULL;
4979                         if ((tp - trap) != 0)
4980                                 setsignal(tp - trap);
4981                 }
4982         }
4983         may_have_traps = 0;
4984         INT_ON;
4985 }
4986
4987 /* Lives far away from here, needed for forkchild */
4988 static void closescript(void);
4989
4990 /* Called after fork(), in child */
4991 /* jp and n are NULL when called by openhere() for heredoc support */
4992 static NOINLINE void
4993 forkchild(struct job *jp, union node *n, int mode)
4994 {
4995         int oldlvl;
4996
4997         TRACE(("Child shell %d\n", getpid()));
4998         oldlvl = shlvl;
4999         shlvl++;
5000
5001         /* man bash: "Non-builtin commands run by bash have signal handlers
5002          * set to the values inherited by the shell from its parent".
5003          * Do we do it correctly? */
5004
5005         closescript();
5006
5007         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5008          && n && n->type == NCMD        /* is it single cmd? */
5009         /* && n->ncmd.args->type == NARG - always true? */
5010          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5011          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5012         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5013         ) {
5014                 TRACE(("Trap hack\n"));
5015                 /* Awful hack for `trap` or $(trap).
5016                  *
5017                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5018                  * contains an example where "trap" is executed in a subshell:
5019                  *
5020                  * save_traps=$(trap)
5021                  * ...
5022                  * eval "$save_traps"
5023                  *
5024                  * Standard does not say that "trap" in subshell shall print
5025                  * parent shell's traps. It only says that its output
5026                  * must have suitable form, but then, in the above example
5027                  * (which is not supposed to be normative), it implies that.
5028                  *
5029                  * bash (and probably other shell) does implement it
5030                  * (traps are reset to defaults, but "trap" still shows them),
5031                  * but as a result, "trap" logic is hopelessly messed up:
5032                  *
5033                  * # trap
5034                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5035                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5036                  * # true | trap   <--- trap is in subshell - no output (ditto)
5037                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5038                  * trap -- 'echo Ho' SIGWINCH
5039                  * # echo `(trap)`         <--- in subshell in subshell - output
5040                  * trap -- 'echo Ho' SIGWINCH
5041                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5042                  * trap -- 'echo Ho' SIGWINCH
5043                  *
5044                  * The rules when to forget and when to not forget traps
5045                  * get really complex and nonsensical.
5046                  *
5047                  * Our solution: ONLY bare $(trap) or `trap` is special.
5048                  */
5049                 /* Save trap handler strings for trap builtin to print */
5050                 trap_ptr = xmemdup(trap, sizeof(trap));
5051                 /* Fall through into clearing traps */
5052         }
5053         clear_traps();
5054 #if JOBS
5055         /* do job control only in root shell */
5056         doing_jobctl = 0;
5057         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5058                 pid_t pgrp;
5059
5060                 if (jp->nprocs == 0)
5061                         pgrp = getpid();
5062                 else
5063                         pgrp = jp->ps[0].ps_pid;
5064                 /* this can fail because we are doing it in the parent also */
5065                 setpgid(0, pgrp);
5066                 if (mode == FORK_FG)
5067                         xtcsetpgrp(ttyfd, pgrp);
5068                 setsignal(SIGTSTP);
5069                 setsignal(SIGTTOU);
5070         } else
5071 #endif
5072         if (mode == FORK_BG) {
5073                 /* man bash: "When job control is not in effect,
5074                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5075                 ignoresig(SIGINT);
5076                 ignoresig(SIGQUIT);
5077                 if (jp->nprocs == 0) {
5078                         close(0);
5079                         if (open(bb_dev_null, O_RDONLY) != 0)
5080                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5081                 }
5082         }
5083         if (oldlvl == 0) {
5084                 if (iflag) { /* why if iflag only? */
5085                         setsignal(SIGINT);
5086                         setsignal(SIGTERM);
5087                 }
5088                 /* man bash:
5089                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5090                  * commands run by bash have signal handlers
5091                  * set to the values inherited by the shell
5092                  * from its parent".
5093                  * Take care of the second rule: */
5094                 setsignal(SIGQUIT);
5095         }
5096 #if JOBS
5097         if (n && n->type == NCMD
5098          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5099         ) {
5100                 TRACE(("Job hack\n"));
5101                 /* "jobs": we do not want to clear job list for it,
5102                  * instead we remove only _its_ own_ job from job list.
5103                  * This makes "jobs .... | cat" more useful.
5104                  */
5105                 freejob(curjob);
5106                 return;
5107         }
5108 #endif
5109         for (jp = curjob; jp; jp = jp->prev_job)
5110                 freejob(jp);
5111         jobless = 0;
5112 }
5113
5114 /* Called after fork(), in parent */
5115 #if !JOBS
5116 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5117 #endif
5118 static void
5119 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5120 {
5121         TRACE(("In parent shell: child = %d\n", pid));
5122         if (!jp) {
5123                 /* jp is NULL when called by openhere() for heredoc support */
5124                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5125                         continue;
5126                 jobless++;
5127                 return;
5128         }
5129 #if JOBS
5130         if (mode != FORK_NOJOB && jp->jobctl) {
5131                 int pgrp;
5132
5133                 if (jp->nprocs == 0)
5134                         pgrp = pid;
5135                 else
5136                         pgrp = jp->ps[0].ps_pid;
5137                 /* This can fail because we are doing it in the child also */
5138                 setpgid(pid, pgrp);
5139         }
5140 #endif
5141         if (mode == FORK_BG) {
5142                 backgndpid = pid;               /* set $! */
5143                 set_curjob(jp, CUR_RUNNING);
5144         }
5145         if (jp) {
5146                 struct procstat *ps = &jp->ps[jp->nprocs++];
5147                 ps->ps_pid = pid;
5148                 ps->ps_status = -1;
5149                 ps->ps_cmd = nullstr;
5150 #if JOBS
5151                 if (doing_jobctl && n)
5152                         ps->ps_cmd = commandtext(n);
5153 #endif
5154         }
5155 }
5156
5157 /* jp and n are NULL when called by openhere() for heredoc support */
5158 static int
5159 forkshell(struct job *jp, union node *n, int mode)
5160 {
5161         int pid;
5162
5163         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5164         pid = fork();
5165         if (pid < 0) {
5166                 TRACE(("Fork failed, errno=%d", errno));
5167                 if (jp)
5168                         freejob(jp);
5169                 ash_msg_and_raise_perror("can't fork");
5170         }
5171         if (pid == 0) {
5172                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5173                 forkchild(jp, n, mode);
5174         } else {
5175                 forkparent(jp, n, mode, pid);
5176         }
5177         return pid;
5178 }
5179
5180 /*
5181  * Wait for job to finish.
5182  *
5183  * Under job control we have the problem that while a child process
5184  * is running interrupts generated by the user are sent to the child
5185  * but not to the shell.  This means that an infinite loop started by
5186  * an interactive user may be hard to kill.  With job control turned off,
5187  * an interactive user may place an interactive program inside a loop.
5188  * If the interactive program catches interrupts, the user doesn't want
5189  * these interrupts to also abort the loop.  The approach we take here
5190  * is to have the shell ignore interrupt signals while waiting for a
5191  * foreground process to terminate, and then send itself an interrupt
5192  * signal if the child process was terminated by an interrupt signal.
5193  * Unfortunately, some programs want to do a bit of cleanup and then
5194  * exit on interrupt; unless these processes terminate themselves by
5195  * sending a signal to themselves (instead of calling exit) they will
5196  * confuse this approach.
5197  *
5198  * Called with interrupts off.
5199  */
5200 static int
5201 waitforjob(struct job *jp)
5202 {
5203         int st;
5204
5205         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5206
5207         INT_OFF;
5208         while (jp->state == JOBRUNNING) {
5209                 /* In non-interactive shells, we _can_ get
5210                  * a keyboard signal here and be EINTRed,
5211                  * but we just loop back, waiting for command to complete.
5212                  *
5213                  * man bash:
5214                  * "If bash is waiting for a command to complete and receives
5215                  * a signal for which a trap has been set, the trap
5216                  * will not be executed until the command completes."
5217                  *
5218                  * Reality is that even if trap is not set, bash
5219                  * will not act on the signal until command completes.
5220                  * Try this. sleep5intoff.c:
5221                  * #include <signal.h>
5222                  * #include <unistd.h>
5223                  * int main() {
5224                  *         sigset_t set;
5225                  *         sigemptyset(&set);
5226                  *         sigaddset(&set, SIGINT);
5227                  *         sigaddset(&set, SIGQUIT);
5228                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5229                  *         sleep(5);
5230                  *         return 0;
5231                  * }
5232                  * $ bash -c './sleep5intoff; echo hi'
5233                  * ^C^C^C^C <--- pressing ^C once a second
5234                  * $ _
5235                  * $ bash -c './sleep5intoff; echo hi'
5236                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5237                  * $ _
5238                  */
5239                 dowait(DOWAIT_BLOCK, jp);
5240         }
5241         INT_ON;
5242
5243         st = getstatus(jp);
5244 #if JOBS
5245         if (jp->jobctl) {
5246                 xtcsetpgrp(ttyfd, rootpid);
5247                 restore_tty_if_stopped_or_signaled(jp);
5248
5249                 /*
5250                  * This is truly gross.
5251                  * If we're doing job control, then we did a TIOCSPGRP which
5252                  * caused us (the shell) to no longer be in the controlling
5253                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5254                  * intuit from the subprocess exit status whether a SIGINT
5255                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5256                  */
5257                 if (jp->sigint) /* TODO: do the same with all signals */
5258                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5259         }
5260         if (jp->state == JOBDONE)
5261 #endif
5262                 freejob(jp);
5263         return st;
5264 }
5265
5266 /*
5267  * return 1 if there are stopped jobs, otherwise 0
5268  */
5269 static int
5270 stoppedjobs(void)
5271 {
5272         struct job *jp;
5273         int retval;
5274
5275         retval = 0;
5276         if (job_warning)
5277                 goto out;
5278         jp = curjob;
5279         if (jp && jp->state == JOBSTOPPED) {
5280                 out2str("You have stopped jobs.\n");
5281                 job_warning = 2;
5282                 retval++;
5283         }
5284  out:
5285         return retval;
5286 }
5287
5288
5289 /*
5290  * Code for dealing with input/output redirection.
5291  */
5292
5293 #undef EMPTY
5294 #undef CLOSED
5295 #define EMPTY -2                /* marks an unused slot in redirtab */
5296 #define CLOSED -1               /* marks a slot of previously-closed fd */
5297
5298 /*
5299  * Handle here documents.  Normally we fork off a process to write the
5300  * data to a pipe.  If the document is short, we can stuff the data in
5301  * the pipe without forking.
5302  */
5303 /* openhere needs this forward reference */
5304 static void expandhere(union node *arg, int fd);
5305 static int
5306 openhere(union node *redir)
5307 {
5308         int pip[2];
5309         size_t len = 0;
5310
5311         if (pipe(pip) < 0)
5312                 ash_msg_and_raise_perror("can't create pipe");
5313         if (redir->type == NHERE) {
5314                 len = strlen(redir->nhere.doc->narg.text);
5315                 if (len <= PIPE_BUF) {
5316                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5317                         goto out;
5318                 }
5319         }
5320         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5321                 /* child */
5322                 close(pip[0]);
5323                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5324                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5325                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5326                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5327                 signal(SIGPIPE, SIG_DFL);
5328                 if (redir->type == NHERE)
5329                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5330                 else /* NXHERE */
5331                         expandhere(redir->nhere.doc, pip[1]);
5332                 _exit(EXIT_SUCCESS);
5333         }
5334  out:
5335         close(pip[1]);
5336         return pip[0];
5337 }
5338
5339 static int
5340 openredirect(union node *redir)
5341 {
5342         struct stat sb;
5343         char *fname;
5344         int f;
5345
5346         switch (redir->nfile.type) {
5347 /* Can't happen, our single caller does this itself */
5348 //      case NTOFD:
5349 //      case NFROMFD:
5350 //              return -1;
5351         case NHERE:
5352         case NXHERE:
5353                 return openhere(redir);
5354         }
5355
5356         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5357          * allocated space. Do it only when we know it is safe.
5358          */
5359         fname = redir->nfile.expfname;
5360
5361         switch (redir->nfile.type) {
5362         default:
5363 #if DEBUG
5364                 abort();
5365 #endif
5366         case NFROM:
5367                 f = open(fname, O_RDONLY);
5368                 if (f < 0)
5369                         goto eopen;
5370                 break;
5371         case NFROMTO:
5372                 f = open(fname, O_RDWR|O_CREAT, 0666);
5373                 if (f < 0)
5374                         goto ecreate;
5375                 break;
5376         case NTO:
5377 #if BASH_REDIR_OUTPUT
5378         case NTO2:
5379 #endif
5380                 /* Take care of noclobber mode. */
5381                 if (Cflag) {
5382                         if (stat(fname, &sb) < 0) {
5383                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5384                                 if (f < 0)
5385                                         goto ecreate;
5386                         } else if (!S_ISREG(sb.st_mode)) {
5387                                 f = open(fname, O_WRONLY, 0666);
5388                                 if (f < 0)
5389                                         goto ecreate;
5390                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5391                                         close(f);
5392                                         errno = EEXIST;
5393                                         goto ecreate;
5394                                 }
5395                         } else {
5396                                 errno = EEXIST;
5397                                 goto ecreate;
5398                         }
5399                         break;
5400                 }
5401                 /* FALLTHROUGH */
5402         case NCLOBBER:
5403                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5404                 if (f < 0)
5405                         goto ecreate;
5406                 break;
5407         case NAPPEND:
5408                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5409                 if (f < 0)
5410                         goto ecreate;
5411                 break;
5412         }
5413
5414         return f;
5415  ecreate:
5416         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5417  eopen:
5418         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5419 }
5420
5421 /*
5422  * Copy a file descriptor to be >= 10. Throws exception on error.
5423  */
5424 static int
5425 savefd(int from)
5426 {
5427         int newfd;
5428         int err;
5429
5430         newfd = fcntl(from, F_DUPFD, 10);
5431         err = newfd < 0 ? errno : 0;
5432         if (err != EBADF) {
5433                 if (err)
5434                         ash_msg_and_raise_perror("%d", from);
5435                 close(from);
5436                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5437         }
5438
5439         return newfd;
5440 }
5441 static int
5442 dup2_or_raise(int from, int to)
5443 {
5444         int newfd;
5445
5446         newfd = (from != to) ? dup2(from, to) : to;
5447         if (newfd < 0) {
5448                 /* Happens when source fd is not open: try "echo >&99" */
5449                 ash_msg_and_raise_perror("%d", from);
5450         }
5451         return newfd;
5452 }
5453 static int
5454 dup_CLOEXEC(int fd, int avoid_fd)
5455 {
5456         int newfd;
5457  repeat:
5458         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5459         if (newfd >= 0) {
5460                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5461                         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5462         } else { /* newfd < 0 */
5463                 if (errno == EBUSY)
5464                         goto repeat;
5465                 if (errno == EINTR)
5466                         goto repeat;
5467         }
5468         return newfd;
5469 }
5470 static int
5471 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5472 {
5473         int newfd;
5474  repeat:
5475         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5476         if (newfd < 0) {
5477                 if (errno == EBUSY)
5478                         goto repeat;
5479                 if (errno == EINTR)
5480                         goto repeat;
5481                 /* fd was not open? */
5482                 if (errno == EBADF)
5483                         return fd;
5484                 ash_msg_and_raise_perror("%d", newfd);
5485         }
5486         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5487         close(fd);
5488         return newfd;
5489 }
5490
5491 /* Struct def and variable are moved down to the first usage site */
5492 struct squirrel {
5493         int orig_fd;
5494         int moved_to;
5495 };
5496 struct redirtab {
5497         struct redirtab *next;
5498         int pair_count;
5499         struct squirrel two_fd[];
5500 };
5501 #define redirlist (G_var.redirlist)
5502
5503 static void
5504 add_squirrel_closed(struct redirtab *sq, int fd)
5505 {
5506         int i;
5507
5508         if (!sq)
5509                 return;
5510
5511         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5512                 /* If we collide with an already moved fd... */
5513                 if (fd == sq->two_fd[i].orig_fd) {
5514                         /* Examples:
5515                          * "echo 3>FILE 3>&- 3>FILE"
5516                          * "echo 3>&- 3>FILE"
5517                          * No need for last redirect to insert
5518                          * another "need to close 3" indicator.
5519                          */
5520                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5521                         return;
5522                 }
5523         }
5524         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5525         sq->two_fd[i].orig_fd = fd;
5526         sq->two_fd[i].moved_to = CLOSED;
5527 }
5528
5529 static int
5530 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5531 {
5532         int i, new_fd;
5533
5534         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5535                 avoid_fd = 9;
5536
5537 #if JOBS
5538         if (fd == ttyfd) {
5539                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5540                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5541                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5542                 return 1; /* "we closed fd" */
5543         }
5544 #endif
5545         /* Are we called from redirect(0)? E.g. redirect
5546          * in a forked child. No need to save fds,
5547          * we aren't going to use them anymore, ok to trash.
5548          */
5549         if (!sq)
5550                 return 0;
5551
5552         /* If this one of script's fds? */
5553         if (fd != 0) {
5554                 struct parsefile *pf = g_parsefile;
5555                 while (pf) {
5556                         /* We skip fd == 0 case because of the following:
5557                          * $ ash  # running ash interactively
5558                          * $ . ./script.sh
5559                          * and in script.sh: "exec 9>&0".
5560                          * Even though top-level pf_fd _is_ 0,
5561                          * it's still ok to use it: "read" builtin uses it,
5562                          * why should we cripple "exec" builtin?
5563                          */
5564                         if (fd == pf->pf_fd) {
5565                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5566                                 return 1; /* "we closed fd" */
5567                         }
5568                         pf = pf->prev;
5569                 }
5570         }
5571
5572         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5573
5574         /* First: do we collide with some already moved fds? */
5575         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5576                 /* If we collide with an already moved fd... */
5577                 if (fd == sq->two_fd[i].moved_to) {
5578                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5579                         sq->two_fd[i].moved_to = new_fd;
5580                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5581                         if (new_fd < 0) /* what? */
5582                                 xfunc_die();
5583                         return 0; /* "we did not close fd" */
5584                 }
5585                 if (fd == sq->two_fd[i].orig_fd) {
5586                         /* Example: echo Hello >/dev/null 1>&2 */
5587                         TRACE(("redirect_fd %d: already moved\n", fd));
5588                         return 0; /* "we did not close fd" */
5589                 }
5590         }
5591
5592         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5593         new_fd = dup_CLOEXEC(fd, avoid_fd);
5594         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5595         if (new_fd < 0) {
5596                 if (errno != EBADF)
5597                         xfunc_die();
5598                 /* new_fd = CLOSED; - already is -1 */
5599         }
5600         sq->two_fd[i].moved_to = new_fd;
5601         sq->two_fd[i].orig_fd = fd;
5602
5603         /* if we move stderr, let "set -x" code know */
5604         if (fd == preverrout_fd)
5605                 preverrout_fd = new_fd;
5606
5607         return 0; /* "we did not close fd" */
5608 }
5609
5610 static int
5611 internally_opened_fd(int fd, struct redirtab *sq)
5612 {
5613         int i;
5614 #if JOBS
5615         if (fd == ttyfd)
5616                 return 1;
5617 #endif
5618         /* If this one of script's fds? */
5619         if (fd != 0) {
5620                 struct parsefile *pf = g_parsefile;
5621                 while (pf) {
5622                         if (fd == pf->pf_fd)
5623                                 return 1;
5624                         pf = pf->prev;
5625                 }
5626         }
5627
5628         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5629                 if (fd == sq->two_fd[i].moved_to)
5630                         return 1;
5631         }
5632         return 0;
5633 }
5634
5635 /*
5636  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5637  * old file descriptors are stashed away so that the redirection can be
5638  * undone by calling popredir.
5639  */
5640 /* flags passed to redirect */
5641 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5642 static void
5643 redirect(union node *redir, int flags)
5644 {
5645         struct redirtab *sv;
5646
5647         if (!redir)
5648                 return;
5649
5650         sv = NULL;
5651         INT_OFF;
5652         if (flags & REDIR_PUSH)
5653                 sv = redirlist;
5654         do {
5655                 int fd;
5656                 int newfd;
5657                 int close_fd;
5658                 int closed;
5659
5660                 fd = redir->nfile.fd;
5661                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5662                         //bb_error_msg("doing %d > %d", fd, newfd);
5663                         newfd = redir->ndup.dupfd;
5664                         close_fd = -1;
5665                 } else {
5666                         newfd = openredirect(redir); /* always >= 0 */
5667                         if (fd == newfd) {
5668                                 /* open() gave us precisely the fd we wanted.
5669                                  * This means that this fd was not busy
5670                                  * (not opened to anywhere).
5671                                  * Remember to close it on restore:
5672                                  */
5673                                 add_squirrel_closed(sv, fd);
5674                                 continue;
5675                         }
5676                         close_fd = newfd;
5677                 }
5678
5679                 if (fd == newfd)
5680                         continue;
5681
5682                 /* if "N>FILE": move newfd to fd */
5683                 /* if "N>&M": dup newfd to fd */
5684                 /* if "N>&-": close fd (newfd is -1) */
5685
5686  IF_BASH_REDIR_OUTPUT(redirect_more:)
5687
5688                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5689                 if (newfd == -1) {
5690                         /* "N>&-" means "close me" */
5691                         if (!closed) {
5692                                 /* ^^^ optimization: saving may already
5693                                  * have closed it. If not... */
5694                                 close(fd);
5695                         }
5696                 } else {
5697                         /* if newfd is a script fd or saved fd, simulate EBADF */
5698                         if (internally_opened_fd(newfd, sv)) {
5699                                 errno = EBADF;
5700                                 ash_msg_and_raise_perror("%d", newfd);
5701                         }
5702                         dup2_or_raise(newfd, fd);
5703                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5704                                 close(close_fd);
5705 #if BASH_REDIR_OUTPUT
5706                         if (redir->nfile.type == NTO2 && fd == 1) {
5707                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5708                                 fd = 2;
5709                                 newfd = 1;
5710                                 close_fd = -1;
5711                                 goto redirect_more;
5712                         }
5713 #endif
5714                 }
5715         } while ((redir = redir->nfile.next) != NULL);
5716         INT_ON;
5717
5718 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5719 #define REDIR_SAVEFD2 0
5720         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5721         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5722         // not only for calls with flags containing REDIR_SAVEFD2.
5723         // We do this unconditionally (see save_fd_on_redirect()).
5724         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5725         //      preverrout_fd = copied_fd2;
5726 }
5727
5728 static int
5729 redirectsafe(union node *redir, int flags)
5730 {
5731         int err;
5732         volatile int saveint;
5733         struct jmploc *volatile savehandler = exception_handler;
5734         struct jmploc jmploc;
5735
5736         SAVE_INT(saveint);
5737         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5738         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5739         if (!err) {
5740                 exception_handler = &jmploc;
5741                 redirect(redir, flags);
5742         }
5743         exception_handler = savehandler;
5744         if (err && exception_type != EXERROR)
5745                 longjmp(exception_handler->loc, 1);
5746         RESTORE_INT(saveint);
5747         return err;
5748 }
5749
5750 static struct redirtab*
5751 pushredir(union node *redir)
5752 {
5753         struct redirtab *sv;
5754         int i;
5755
5756         if (!redir)
5757                 return redirlist;
5758
5759         i = 0;
5760         do {
5761                 i++;
5762 #if BASH_REDIR_OUTPUT
5763                 if (redir->nfile.type == NTO2)
5764                         i++;
5765 #endif
5766                 redir = redir->nfile.next;
5767         } while (redir);
5768
5769         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5770         sv->pair_count = i;
5771         while (--i >= 0)
5772                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5773         sv->next = redirlist;
5774         redirlist = sv;
5775         return sv->next;
5776 }
5777
5778 /*
5779  * Undo the effects of the last redirection.
5780  */
5781 static void
5782 popredir(int drop)
5783 {
5784         struct redirtab *rp;
5785         int i;
5786
5787         if (redirlist == NULL)
5788                 return;
5789         INT_OFF;
5790         rp = redirlist;
5791         for (i = 0; i < rp->pair_count; i++) {
5792                 int fd = rp->two_fd[i].orig_fd;
5793                 int copy = rp->two_fd[i].moved_to;
5794                 if (copy == CLOSED) {
5795                         if (!drop)
5796                                 close(fd);
5797                         continue;
5798                 }
5799                 if (copy != EMPTY) {
5800                         if (!drop) {
5801                                 /*close(fd);*/
5802                                 dup2_or_raise(copy, fd);
5803                         }
5804                         close(copy);
5805                 }
5806         }
5807         redirlist = rp->next;
5808         free(rp);
5809         INT_ON;
5810 }
5811
5812 static void
5813 unwindredir(struct redirtab *stop)
5814 {
5815         while (redirlist != stop)
5816                 popredir(/*drop:*/ 0);
5817 }
5818
5819
5820 /* ============ Routines to expand arguments to commands
5821  *
5822  * We have to deal with backquotes, shell variables, and file metacharacters.
5823  */
5824
5825 #if ENABLE_FEATURE_SH_MATH
5826 static arith_t
5827 ash_arith(const char *s)
5828 {
5829         arith_state_t math_state;
5830         arith_t result;
5831
5832         math_state.lookupvar = lookupvar;
5833         math_state.setvar    = setvar0;
5834         //math_state.endofname = endofname;
5835
5836         INT_OFF;
5837         result = arith(&math_state, s);
5838         if (math_state.errmsg)
5839                 ash_msg_and_raise_error(math_state.errmsg);
5840         INT_ON;
5841
5842         return result;
5843 }
5844 #endif
5845 #if BASH_SUBSTR
5846 # if ENABLE_FEATURE_SH_MATH
5847 static int substr_atoi(const char *s)
5848 {
5849         arith_t t = ash_arith(s);
5850         if (sizeof(t) > sizeof(int)) {
5851                 /* clamp very large or very large negative nums for ${v:N:M}:
5852                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5853                  */
5854                 if (t > INT_MAX)
5855                         t = INT_MAX;
5856                 if (t < INT_MIN)
5857                         t = INT_MIN;
5858         }
5859         return t;
5860 }
5861 # else
5862 #  define substr_atoi(s) number(s)
5863 # endif
5864 #endif
5865
5866 /*
5867  * expandarg flags
5868  */
5869 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5870 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5871 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5872 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5873 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5874  * POSIX says for this case:
5875  *  Pathname expansion shall not be performed on the word by a
5876  *  non-interactive shell; an interactive shell may perform it, but shall
5877  *  do so only when the expansion would result in one word.
5878  * Currently, our code complies to the above rule by never globbing
5879  * redirection filenames.
5880  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5881  * (this means that on a typical Linux distro, bash almost always
5882  * performs globbing, and thus diverges from what we do).
5883  */
5884 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5885 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5886 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5887 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5888 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5889 /*
5890  * rmescape() flags
5891  */
5892 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5893 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5894 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5895 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5896
5897 /* Add CTLESC when necessary. */
5898 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5899 /* Do not skip NUL characters. */
5900 #define QUOTES_KEEPNUL EXP_TILDE
5901
5902 /*
5903  * Structure specifying which parts of the string should be searched
5904  * for IFS characters.
5905  */
5906 struct ifsregion {
5907         struct ifsregion *next; /* next region in list */
5908         int begoff;             /* offset of start of region */
5909         int endoff;             /* offset of end of region */
5910         int nulonly;            /* search for nul bytes only */
5911 };
5912
5913 struct arglist {
5914         struct strlist *list;
5915         struct strlist **lastp;
5916 };
5917
5918 /* output of current string */
5919 static char *expdest;
5920 /* list of back quote expressions */
5921 static struct nodelist *argbackq;
5922 /* first struct in list of ifs regions */
5923 static struct ifsregion ifsfirst;
5924 /* last struct in list */
5925 static struct ifsregion *ifslastp;
5926 /* holds expanded arg list */
5927 static struct arglist exparg;
5928
5929 /*
5930  * Our own itoa().
5931  * cvtnum() is used even if math support is off (to prepare $? values and such).
5932  */
5933 static int
5934 cvtnum(arith_t num)
5935 {
5936         int len;
5937
5938         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5939         len = sizeof(arith_t) * 3;
5940         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5941         if (sizeof(arith_t) < 4) len += 2;
5942
5943         expdest = makestrspace(len, expdest);
5944         len = fmtstr(expdest, len, ARITH_FMT, num);
5945         STADJUST(len, expdest);
5946         return len;
5947 }
5948
5949 /*
5950  * Break the argument string into pieces based upon IFS and add the
5951  * strings to the argument list.  The regions of the string to be
5952  * searched for IFS characters have been stored by recordregion.
5953  */
5954 static void
5955 ifsbreakup(char *string, struct arglist *arglist)
5956 {
5957         struct ifsregion *ifsp;
5958         struct strlist *sp;
5959         char *start;
5960         char *p;
5961         char *q;
5962         const char *ifs, *realifs;
5963         int ifsspc;
5964         int nulonly;
5965
5966         start = string;
5967         if (ifslastp != NULL) {
5968                 ifsspc = 0;
5969                 nulonly = 0;
5970                 realifs = ifsset() ? ifsval() : defifs;
5971                 ifsp = &ifsfirst;
5972                 do {
5973                         p = string + ifsp->begoff;
5974                         nulonly = ifsp->nulonly;
5975                         ifs = nulonly ? nullstr : realifs;
5976                         ifsspc = 0;
5977                         while (p < string + ifsp->endoff) {
5978                                 q = p;
5979                                 if ((unsigned char)*p == CTLESC)
5980                                         p++;
5981                                 if (!strchr(ifs, *p)) {
5982                                         p++;
5983                                         continue;
5984                                 }
5985                                 if (!nulonly)
5986                                         ifsspc = (strchr(defifs, *p) != NULL);
5987                                 /* Ignore IFS whitespace at start */
5988                                 if (q == start && ifsspc) {
5989                                         p++;
5990                                         start = p;
5991                                         continue;
5992                                 }
5993                                 *q = '\0';
5994                                 sp = stzalloc(sizeof(*sp));
5995                                 sp->text = start;
5996                                 *arglist->lastp = sp;
5997                                 arglist->lastp = &sp->next;
5998                                 p++;
5999                                 if (!nulonly) {
6000                                         for (;;) {
6001                                                 if (p >= string + ifsp->endoff) {
6002                                                         break;
6003                                                 }
6004                                                 q = p;
6005                                                 if ((unsigned char)*p == CTLESC)
6006                                                         p++;
6007                                                 if (strchr(ifs, *p) == NULL) {
6008                                                         p = q;
6009                                                         break;
6010                                                 }
6011                                                 if (strchr(defifs, *p) == NULL) {
6012                                                         if (ifsspc) {
6013                                                                 p++;
6014                                                                 ifsspc = 0;
6015                                                         } else {
6016                                                                 p = q;
6017                                                                 break;
6018                                                         }
6019                                                 } else
6020                                                         p++;
6021                                         }
6022                                 }
6023                                 start = p;
6024                         } /* while */
6025                         ifsp = ifsp->next;
6026                 } while (ifsp != NULL);
6027                 if (nulonly)
6028                         goto add;
6029         }
6030
6031         if (!*start)
6032                 return;
6033
6034  add:
6035         sp = stzalloc(sizeof(*sp));
6036         sp->text = start;
6037         *arglist->lastp = sp;
6038         arglist->lastp = &sp->next;
6039 }
6040
6041 static void
6042 ifsfree(void)
6043 {
6044         struct ifsregion *p = ifsfirst.next;
6045
6046         if (!p)
6047                 goto out;
6048
6049         INT_OFF;
6050         do {
6051                 struct ifsregion *ifsp;
6052                 ifsp = p->next;
6053                 free(p);
6054                 p = ifsp;
6055         } while (p);
6056         ifsfirst.next = NULL;
6057         INT_ON;
6058  out:
6059         ifslastp = NULL;
6060 }
6061
6062 static size_t
6063 esclen(const char *start, const char *p)
6064 {
6065         size_t esc = 0;
6066
6067         while (p > start && (unsigned char)*--p == CTLESC) {
6068                 esc++;
6069         }
6070         return esc;
6071 }
6072
6073 /*
6074  * Remove any CTLESC characters from a string.
6075  */
6076 #if !BASH_PATTERN_SUBST
6077 #define rmescapes(str, flag, slash_position) \
6078         rmescapes(str, flag)
6079 #endif
6080 static char *
6081 rmescapes(char *str, int flag, int *slash_position)
6082 {
6083         static const char qchars[] ALIGN1 = {
6084                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6085
6086         char *p, *q, *r;
6087         unsigned inquotes;
6088         unsigned protect_against_glob;
6089         unsigned globbing;
6090
6091         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6092         if (!p)
6093                 return str;
6094
6095         q = p;
6096         r = str;
6097         if (flag & RMESCAPE_ALLOC) {
6098                 size_t len = p - str;
6099                 size_t fulllen = len + strlen(p) + 1;
6100
6101                 if (flag & RMESCAPE_GROW) {
6102                         int strloc = str - (char *)stackblock();
6103                         r = makestrspace(fulllen, expdest);
6104                         /* p and str may be invalidated by makestrspace */
6105                         str = (char *)stackblock() + strloc;
6106                         p = str + len;
6107                 } else if (flag & RMESCAPE_HEAP) {
6108                         r = ckmalloc(fulllen);
6109                 } else {
6110                         r = stalloc(fulllen);
6111                 }
6112                 q = r;
6113                 if (len > 0) {
6114                         q = (char *)mempcpy(q, str, len);
6115                 }
6116         }
6117
6118         inquotes = 0;
6119         globbing = flag & RMESCAPE_GLOB;
6120         protect_against_glob = globbing;
6121         while (*p) {
6122                 if ((unsigned char)*p == CTLQUOTEMARK) {
6123 // Note: both inquotes and protect_against_glob only affect whether
6124 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6125                         inquotes = ~inquotes;
6126                         p++;
6127                         protect_against_glob = globbing;
6128                         continue;
6129                 }
6130                 if ((unsigned char)*p == CTLESC) {
6131                         p++;
6132 #if DEBUG
6133                         if (*p == '\0')
6134                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6135 #endif
6136                         if (protect_against_glob) {
6137                                 /*
6138                                  * We used to trust glob() and fnmatch() to eat
6139                                  * superfluous escapes (\z where z has no
6140                                  * special meaning anyway). But this causes
6141                                  * bugs such as string of one greek letter rho
6142                                  * (unicode-encoded as two bytes "cf,81")
6143                                  * getting encoded as "cf,CTLESC,81"
6144                                  * and here, converted to "cf,\,81" -
6145                                  * which does not go well with some flavors
6146                                  * of fnmatch() in unicode locales
6147                                  * (for example, glibc <= 2.22).
6148                                  *
6149                                  * Lets add "\" only on the chars which need it.
6150                                  * Testcases for less obvious chars are shown.
6151                                  */
6152                                 if (*p == '*'
6153                                  || *p == '?'
6154                                  || *p == '['
6155                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6156                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6157                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6158                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6159                                 /* Some libc support [^negate], that's why "^" also needs love */
6160                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6161                                 ) {
6162                                         *q++ = '\\';
6163                                 }
6164                         }
6165                 } else if (*p == '\\' && !inquotes) {
6166                         /* naked back slash */
6167                         protect_against_glob = 0;
6168                         goto copy;
6169                 }
6170 #if BASH_PATTERN_SUBST
6171                 else if (slash_position && p == str + *slash_position) {
6172                         /* stop handling globbing */
6173                         globbing = 0;
6174                         *slash_position = q - r;
6175                         slash_position = NULL;
6176                 }
6177 #endif
6178                 protect_against_glob = globbing;
6179  copy:
6180                 *q++ = *p++;
6181         }
6182         *q = '\0';
6183         if (flag & RMESCAPE_GROW) {
6184                 expdest = r;
6185                 STADJUST(q - r + 1, expdest);
6186         }
6187         return r;
6188 }
6189 #define pmatch(a, b) !fnmatch((a), (b), 0)
6190
6191 /*
6192  * Prepare a pattern for a expmeta (internal glob(3)) call.
6193  *
6194  * Returns an stalloced string.
6195  */
6196 static char *
6197 preglob(const char *pattern, int flag)
6198 {
6199         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6200 }
6201
6202 /*
6203  * Put a string on the stack.
6204  */
6205 static void
6206 memtodest(const char *p, size_t len, int syntax, int quotes)
6207 {
6208         char *q;
6209
6210         if (!len)
6211                 return;
6212
6213         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6214
6215         do {
6216                 unsigned char c = *p++;
6217                 if (c) {
6218                         if (quotes & QUOTES_ESC) {
6219                                 int n = SIT(c, syntax);
6220                                 if (n == CCTL
6221                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6222                                      && n == CBACK
6223                                     )
6224                                 ) {
6225                                         USTPUTC(CTLESC, q);
6226                                 }
6227                         }
6228                 } else if (!(quotes & QUOTES_KEEPNUL))
6229                         continue;
6230                 USTPUTC(c, q);
6231         } while (--len);
6232
6233         expdest = q;
6234 }
6235
6236 static size_t
6237 strtodest(const char *p, int syntax, int quotes)
6238 {
6239         size_t len = strlen(p);
6240         memtodest(p, len, syntax, quotes);
6241         return len;
6242 }
6243
6244 /*
6245  * Record the fact that we have to scan this region of the
6246  * string for IFS characters.
6247  */
6248 static void
6249 recordregion(int start, int end, int nulonly)
6250 {
6251         struct ifsregion *ifsp;
6252
6253         if (ifslastp == NULL) {
6254                 ifsp = &ifsfirst;
6255         } else {
6256                 INT_OFF;
6257                 ifsp = ckzalloc(sizeof(*ifsp));
6258                 /*ifsp->next = NULL; - ckzalloc did it */
6259                 ifslastp->next = ifsp;
6260                 INT_ON;
6261         }
6262         ifslastp = ifsp;
6263         ifslastp->begoff = start;
6264         ifslastp->endoff = end;
6265         ifslastp->nulonly = nulonly;
6266 }
6267
6268 static void
6269 removerecordregions(int endoff)
6270 {
6271         if (ifslastp == NULL)
6272                 return;
6273
6274         if (ifsfirst.endoff > endoff) {
6275                 while (ifsfirst.next) {
6276                         struct ifsregion *ifsp;
6277                         INT_OFF;
6278                         ifsp = ifsfirst.next->next;
6279                         free(ifsfirst.next);
6280                         ifsfirst.next = ifsp;
6281                         INT_ON;
6282                 }
6283                 if (ifsfirst.begoff > endoff) {
6284                         ifslastp = NULL;
6285                 } else {
6286                         ifslastp = &ifsfirst;
6287                         ifsfirst.endoff = endoff;
6288                 }
6289                 return;
6290         }
6291
6292         ifslastp = &ifsfirst;
6293         while (ifslastp->next && ifslastp->next->begoff < endoff)
6294                 ifslastp = ifslastp->next;
6295         while (ifslastp->next) {
6296                 struct ifsregion *ifsp;
6297                 INT_OFF;
6298                 ifsp = ifslastp->next->next;
6299                 free(ifslastp->next);
6300                 ifslastp->next = ifsp;
6301                 INT_ON;
6302         }
6303         if (ifslastp->endoff > endoff)
6304                 ifslastp->endoff = endoff;
6305 }
6306
6307 static char *
6308 exptilde(char *startp, char *p, int flags)
6309 {
6310         unsigned char c;
6311         char *name;
6312         struct passwd *pw;
6313         const char *home;
6314         int quotes = flags & QUOTES_ESC;
6315
6316         name = p + 1;
6317
6318         while ((c = *++p) != '\0') {
6319                 switch (c) {
6320                 case CTLESC:
6321                         return startp;
6322                 case CTLQUOTEMARK:
6323                         return startp;
6324                 case ':':
6325                         if (flags & EXP_VARTILDE)
6326                                 goto done;
6327                         break;
6328                 case '/':
6329                 case CTLENDVAR:
6330                         goto done;
6331                 }
6332         }
6333  done:
6334         *p = '\0';
6335         if (*name == '\0') {
6336                 home = lookupvar("HOME");
6337         } else {
6338                 pw = getpwnam(name);
6339                 if (pw == NULL)
6340                         goto lose;
6341                 home = pw->pw_dir;
6342         }
6343         if (!home || !*home)
6344                 goto lose;
6345         *p = c;
6346         strtodest(home, SQSYNTAX, quotes);
6347         return p;
6348  lose:
6349         *p = c;
6350         return startp;
6351 }
6352
6353 /*
6354  * Execute a command inside back quotes.  If it's a builtin command, we
6355  * want to save its output in a block obtained from malloc.  Otherwise
6356  * we fork off a subprocess and get the output of the command via a pipe.
6357  * Should be called with interrupts off.
6358  */
6359 struct backcmd {                /* result of evalbackcmd */
6360         int fd;                 /* file descriptor to read from */
6361         int nleft;              /* number of chars in buffer */
6362         char *buf;              /* buffer */
6363         struct job *jp;         /* job structure for command */
6364 };
6365
6366 /* These forward decls are needed to use "eval" code for backticks handling: */
6367 /* flags in argument to evaltree */
6368 #define EV_EXIT    01           /* exit after evaluating tree */
6369 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6370 static int evaltree(union node *, int);
6371
6372 /* An evaltree() which is known to never return.
6373  * Used to use an alias:
6374  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6375  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6376  */
6377 static ALWAYS_INLINE NORETURN void
6378 evaltreenr(union node *n, int flags)
6379 {
6380         evaltree(n, flags);
6381         bb_unreachable(abort());
6382         /* NOTREACHED */
6383 }
6384
6385 static void FAST_FUNC
6386 evalbackcmd(union node *n, struct backcmd *result)
6387 {
6388         int pip[2];
6389         struct job *jp;
6390
6391         result->fd = -1;
6392         result->buf = NULL;
6393         result->nleft = 0;
6394         result->jp = NULL;
6395         if (n == NULL) {
6396                 goto out;
6397         }
6398
6399         if (pipe(pip) < 0)
6400                 ash_msg_and_raise_perror("can't create pipe");
6401         jp = makejob(/*n,*/ 1);
6402         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6403                 /* child */
6404                 FORCE_INT_ON;
6405                 close(pip[0]);
6406                 if (pip[1] != 1) {
6407                         /*close(1);*/
6408                         dup2_or_raise(pip[1], 1);
6409                         close(pip[1]);
6410                 }
6411 /* TODO: eflag clearing makes the following not abort:
6412  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6413  * which is what bash does (unless it is in POSIX mode).
6414  * dash deleted "eflag = 0" line in the commit
6415  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6416  *  [EVAL] Don't clear eflag in evalbackcmd
6417  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6418  */
6419                 eflag = 0;
6420                 ifsfree();
6421                 evaltreenr(n, EV_EXIT);
6422                 /* NOTREACHED */
6423         }
6424         /* parent */
6425         close(pip[1]);
6426         result->fd = pip[0];
6427         result->jp = jp;
6428
6429  out:
6430         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6431                 result->fd, result->buf, result->nleft, result->jp));
6432 }
6433
6434 /*
6435  * Expand stuff in backwards quotes.
6436  */
6437 static void
6438 expbackq(union node *cmd, int flag)
6439 {
6440         struct backcmd in;
6441         int i;
6442         char buf[128];
6443         char *p;
6444         char *dest;
6445         int startloc;
6446         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6447         struct stackmark smark;
6448
6449         INT_OFF;
6450         startloc = expdest - (char *)stackblock();
6451         pushstackmark(&smark, startloc);
6452         evalbackcmd(cmd, &in);
6453         popstackmark(&smark);
6454
6455         p = in.buf;
6456         i = in.nleft;
6457         if (i == 0)
6458                 goto read;
6459         for (;;) {
6460                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6461  read:
6462                 if (in.fd < 0)
6463                         break;
6464                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6465                 TRACE(("expbackq: read returns %d\n", i));
6466                 if (i <= 0)
6467                         break;
6468                 p = buf;
6469         }
6470
6471         free(in.buf);
6472         if (in.fd >= 0) {
6473                 close(in.fd);
6474                 back_exitstatus = waitforjob(in.jp);
6475         }
6476         INT_ON;
6477
6478         /* Eat all trailing newlines */
6479         dest = expdest;
6480         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6481                 STUNPUTC(dest);
6482         expdest = dest;
6483
6484         if (!(flag & EXP_QUOTED))
6485                 recordregion(startloc, dest - (char *)stackblock(), 0);
6486         TRACE(("evalbackq: size:%d:'%.*s'\n",
6487                 (int)((dest - (char *)stackblock()) - startloc),
6488                 (int)((dest - (char *)stackblock()) - startloc),
6489                 stackblock() + startloc));
6490 }
6491
6492 #if ENABLE_FEATURE_SH_MATH
6493 /*
6494  * Expand arithmetic expression.  Backup to start of expression,
6495  * evaluate, place result in (backed up) result, adjust string position.
6496  */
6497 static void
6498 expari(int flag)
6499 {
6500         char *p, *start;
6501         int begoff;
6502         int len;
6503
6504         /* ifsfree(); */
6505
6506         /*
6507          * This routine is slightly over-complicated for
6508          * efficiency.  Next we scan backwards looking for the
6509          * start of arithmetic.
6510          */
6511         start = stackblock();
6512         p = expdest - 1;
6513         *p = '\0';
6514         p--;
6515         while (1) {
6516                 int esc;
6517
6518                 while ((unsigned char)*p != CTLARI) {
6519                         p--;
6520 #if DEBUG
6521                         if (p < start) {
6522                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6523                         }
6524 #endif
6525                 }
6526
6527                 esc = esclen(start, p);
6528                 if (!(esc % 2)) {
6529                         break;
6530                 }
6531
6532                 p -= esc + 1;
6533         }
6534
6535         begoff = p - start;
6536
6537         removerecordregions(begoff);
6538
6539         expdest = p;
6540
6541         if (flag & QUOTES_ESC)
6542                 rmescapes(p + 1, 0, NULL);
6543
6544         len = cvtnum(ash_arith(p + 1));
6545
6546         if (!(flag & EXP_QUOTED))
6547                 recordregion(begoff, begoff + len, 0);
6548 }
6549 #endif
6550
6551 /* argstr needs it */
6552 static char *evalvar(char *p, int flags);
6553
6554 /*
6555  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6556  * characters to allow for further processing.  Otherwise treat
6557  * $@ like $* since no splitting will be performed.
6558  */
6559 static void
6560 argstr(char *p, int flags)
6561 {
6562         static const char spclchars[] ALIGN1 = {
6563                 '=',
6564                 ':',
6565                 CTLQUOTEMARK,
6566                 CTLENDVAR,
6567                 CTLESC,
6568                 CTLVAR,
6569                 CTLBACKQ,
6570 #if ENABLE_FEATURE_SH_MATH
6571                 CTLENDARI,
6572 #endif
6573                 '\0'
6574         };
6575         const char *reject = spclchars;
6576         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6577         int inquotes;
6578         size_t length;
6579         int startloc;
6580
6581         if (!(flags & EXP_VARTILDE)) {
6582                 reject += 2;
6583         } else if (flags & EXP_VARTILDE2) {
6584                 reject++;
6585         }
6586         inquotes = 0;
6587         length = 0;
6588         if (flags & EXP_TILDE) {
6589                 char *q;
6590
6591                 flags &= ~EXP_TILDE;
6592  tilde:
6593                 q = p;
6594                 if (*q == '~')
6595                         p = exptilde(p, q, flags);
6596         }
6597  start:
6598         startloc = expdest - (char *)stackblock();
6599         for (;;) {
6600                 unsigned char c;
6601
6602                 length += strcspn(p + length, reject);
6603                 c = p[length];
6604                 if (c) {
6605                         if (!(c & 0x80)
6606                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6607                         ) {
6608                                 /* c == '=' || c == ':' || c == CTLENDARI */
6609                                 length++;
6610                         }
6611                 }
6612                 if (length > 0) {
6613                         int newloc;
6614                         expdest = stack_nputstr(p, length, expdest);
6615                         newloc = expdest - (char *)stackblock();
6616                         if (breakall && !inquotes && newloc > startloc) {
6617                                 recordregion(startloc, newloc, 0);
6618                         }
6619                         startloc = newloc;
6620                 }
6621                 p += length + 1;
6622                 length = 0;
6623
6624                 switch (c) {
6625                 case '\0':
6626                         goto breakloop;
6627                 case '=':
6628                         if (flags & EXP_VARTILDE2) {
6629                                 p--;
6630                                 continue;
6631                         }
6632                         flags |= EXP_VARTILDE2;
6633                         reject++;
6634                         /* fall through */
6635                 case ':':
6636                         /*
6637                          * sort of a hack - expand tildes in variable
6638                          * assignments (after the first '=' and after ':'s).
6639                          */
6640                         if (*--p == '~') {
6641                                 goto tilde;
6642                         }
6643                         continue;
6644                 }
6645
6646                 switch (c) {
6647                 case CTLENDVAR: /* ??? */
6648                         goto breakloop;
6649                 case CTLQUOTEMARK:
6650                         inquotes ^= EXP_QUOTED;
6651                         /* "$@" syntax adherence hack */
6652                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6653                                 p = evalvar(p + 1, flags | inquotes) + 1;
6654                                 goto start;
6655                         }
6656  addquote:
6657                         if (flags & QUOTES_ESC) {
6658                                 p--;
6659                                 length++;
6660                                 startloc++;
6661                         }
6662                         break;
6663                 case CTLESC:
6664                         startloc++;
6665                         length++;
6666
6667                         /*
6668                          * Quoted parameter expansion pattern: remove quote
6669                          * unless inside inner quotes or we have a literal
6670                          * backslash.
6671                          */
6672                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6673                             EXP_QPAT && *p != '\\')
6674                                 break;
6675
6676                         goto addquote;
6677                 case CTLVAR:
6678                         TRACE(("argstr: evalvar('%s')\n", p));
6679                         p = evalvar(p, flags | inquotes);
6680                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6681                         goto start;
6682                 case CTLBACKQ:
6683                         expbackq(argbackq->n, flags | inquotes);
6684                         argbackq = argbackq->next;
6685                         goto start;
6686 #if ENABLE_FEATURE_SH_MATH
6687                 case CTLENDARI:
6688                         p--;
6689                         expari(flags | inquotes);
6690                         goto start;
6691 #endif
6692                 }
6693         }
6694  breakloop: ;
6695 }
6696
6697 static char *
6698 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6699                 char *pattern, int quotes, int zero)
6700 {
6701         char *loc, *loc2;
6702         char c;
6703
6704         loc = startp;
6705         loc2 = rmesc;
6706         do {
6707                 int match;
6708                 const char *s = loc2;
6709
6710                 c = *loc2;
6711                 if (zero) {
6712                         *loc2 = '\0';
6713                         s = rmesc;
6714                 }
6715                 match = pmatch(pattern, s);
6716
6717                 *loc2 = c;
6718                 if (match)
6719                         return loc;
6720                 if (quotes && (unsigned char)*loc == CTLESC)
6721                         loc++;
6722                 loc++;
6723                 loc2++;
6724         } while (c);
6725         return NULL;
6726 }
6727
6728 static char *
6729 scanright(char *startp, char *rmesc, char *rmescend,
6730                 char *pattern, int quotes, int match_at_start)
6731 {
6732 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6733         int try2optimize = match_at_start;
6734 #endif
6735         int esc = 0;
6736         char *loc;
6737         char *loc2;
6738
6739         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6740          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6741          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6742          * Logic:
6743          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6744          * and on each iteration they go back two/one char until they reach the beginning.
6745          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6746          */
6747         /* TODO: document in what other circumstances we are called. */
6748
6749         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6750                 int match;
6751                 char c = *loc2;
6752                 const char *s = loc2;
6753                 if (match_at_start) {
6754                         *loc2 = '\0';
6755                         s = rmesc;
6756                 }
6757                 match = pmatch(pattern, s);
6758                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6759                 *loc2 = c;
6760                 if (match)
6761                         return loc;
6762 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6763                 if (try2optimize) {
6764                         /* Maybe we can optimize this:
6765                          * if pattern ends with unescaped *, we can avoid checking
6766                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6767                          * it won't match truncated "raw_value_of_" strings too.
6768                          */
6769                         unsigned plen = strlen(pattern);
6770                         /* Does it end with "*"? */
6771                         if (plen != 0 && pattern[--plen] == '*') {
6772                                 /* "xxxx*" is not escaped */
6773                                 /* "xxx\*" is escaped */
6774                                 /* "xx\\*" is not escaped */
6775                                 /* "x\\\*" is escaped */
6776                                 int slashes = 0;
6777                                 while (plen != 0 && pattern[--plen] == '\\')
6778                                         slashes++;
6779                                 if (!(slashes & 1))
6780                                         break; /* ends with unescaped "*" */
6781                         }
6782                         try2optimize = 0;
6783                 }
6784 #endif
6785                 loc--;
6786                 if (quotes) {
6787                         if (--esc < 0) {
6788                                 esc = esclen(startp, loc);
6789                         }
6790                         if (esc % 2) {
6791                                 esc--;
6792                                 loc--;
6793                         }
6794                 }
6795         }
6796         return NULL;
6797 }
6798
6799 static void varunset(const char *, const char *, const char *, int) NORETURN;
6800 static void
6801 varunset(const char *end, const char *var, const char *umsg, int varflags)
6802 {
6803         const char *msg;
6804         const char *tail;
6805
6806         tail = nullstr;
6807         msg = "parameter not set";
6808         if (umsg) {
6809                 if ((unsigned char)*end == CTLENDVAR) {
6810                         if (varflags & VSNUL)
6811                                 tail = " or null";
6812                 } else {
6813                         msg = umsg;
6814                 }
6815         }
6816         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6817 }
6818
6819 static const char *
6820 subevalvar(char *p, char *varname, int strloc, int subtype,
6821                 int startloc, int varflags, int flag)
6822 {
6823         struct nodelist *saveargbackq = argbackq;
6824         int quotes = flag & QUOTES_ESC;
6825         char *startp;
6826         char *loc;
6827         char *rmesc, *rmescend;
6828         char *str;
6829         int amount, resetloc;
6830         int argstr_flags;
6831         IF_BASH_PATTERN_SUBST(int workloc;)
6832         IF_BASH_PATTERN_SUBST(int slash_pos;)
6833         IF_BASH_PATTERN_SUBST(char *repl;)
6834         int zero;
6835         char *(*scan)(char*, char*, char*, char*, int, int);
6836
6837         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6838         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6839
6840 #if BASH_PATTERN_SUBST
6841         /* For "${v/pattern/repl}", we must find the delimiter _before_
6842          * argstr() call expands possible variable references in pattern:
6843          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6844          */
6845         repl = NULL;
6846         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6847                 /* Find '/' and replace with NUL */
6848                 repl = p;
6849                 for (;;) {
6850                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6851                         if (*repl == '\0') {
6852                                 repl = NULL;
6853                                 break;
6854                         }
6855                         if (*repl == '/') {
6856                                 *repl = '\0';
6857                                 break;
6858                         }
6859                         if ((unsigned char)*repl == CTLESC && repl[1])
6860                                 repl++;
6861                         repl++;
6862                 }
6863         }
6864 #endif
6865         argstr_flags = EXP_TILDE;
6866         if (subtype != VSASSIGN && subtype != VSQUESTION)
6867                 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
6868         argstr(p, argstr_flags);
6869 #if BASH_PATTERN_SUBST
6870         slash_pos = -1;
6871         if (repl) {
6872                 slash_pos = expdest - ((char *)stackblock() + strloc);
6873                 STPUTC('/', expdest);
6874                 argstr(repl + 1, argstr_flags);
6875                 *repl = '/';
6876         }
6877 #endif
6878         STPUTC('\0', expdest);
6879         argbackq = saveargbackq;
6880         startp = (char *)stackblock() + startloc;
6881         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6882
6883         switch (subtype) {
6884         case VSASSIGN:
6885                 setvar0(varname, startp);
6886                 amount = startp - expdest;
6887                 STADJUST(amount, expdest);
6888                 return startp;
6889
6890         case VSQUESTION:
6891                 varunset(p, varname, startp, varflags);
6892                 /* NOTREACHED */
6893
6894 #if BASH_SUBSTR
6895         case VSSUBSTR: {
6896                 int pos, len, orig_len;
6897                 char *colon;
6898
6899                 loc = str = stackblock() + strloc;
6900
6901                 /* Read POS in ${var:POS:LEN} */
6902                 colon = strchr(loc, ':');
6903                 if (colon) *colon = '\0';
6904                 pos = substr_atoi(loc);
6905                 if (colon) *colon = ':';
6906
6907                 /* Read LEN in ${var:POS:LEN} */
6908                 len = str - startp - 1;
6909                 /* *loc != '\0', guaranteed by parser */
6910                 if (quotes) {
6911                         char *ptr;
6912                         /* Adjust the length by the number of escapes */
6913                         for (ptr = startp; ptr < (str - 1); ptr++) {
6914                                 if ((unsigned char)*ptr == CTLESC) {
6915                                         len--;
6916                                         ptr++;
6917                                 }
6918                         }
6919                 }
6920                 orig_len = len;
6921                 if (*loc++ == ':') {
6922                         /* ${var::LEN} */
6923                         len = substr_atoi(loc);
6924                 } else {
6925                         /* Skip POS in ${var:POS:LEN} */
6926                         len = orig_len;
6927                         while (*loc && *loc != ':')
6928                                 loc++;
6929                         if (*loc++ == ':')
6930                                 len = substr_atoi(loc);
6931                 }
6932                 if (pos < 0) {
6933                         /* ${VAR:$((-n)):l} starts n chars from the end */
6934                         pos = orig_len + pos;
6935                 }
6936                 if ((unsigned)pos >= orig_len) {
6937                         /* apart from obvious ${VAR:999999:l},
6938                          * covers ${VAR:$((-9999999)):l} - result is ""
6939                          * (bash compat)
6940                          */
6941                         pos = 0;
6942                         len = 0;
6943                 }
6944                 if (len < 0) {
6945                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6946                         len = (orig_len - pos) + len;
6947                 }
6948                 if ((unsigned)len > (orig_len - pos))
6949                         len = orig_len - pos;
6950
6951                 for (str = startp; pos; str++, pos--) {
6952                         if (quotes && (unsigned char)*str == CTLESC)
6953                                 str++;
6954                 }
6955                 for (loc = startp; len; len--) {
6956                         if (quotes && (unsigned char)*str == CTLESC)
6957                                 *loc++ = *str++;
6958                         *loc++ = *str++;
6959                 }
6960                 *loc = '\0';
6961                 amount = loc - expdest;
6962                 STADJUST(amount, expdest);
6963                 return loc;
6964         }
6965 #endif /* BASH_SUBSTR */
6966         }
6967
6968         resetloc = expdest - (char *)stackblock();
6969
6970 #if BASH_PATTERN_SUBST
6971         repl = NULL;
6972
6973         /* We'll comeback here if we grow the stack while handling
6974          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6975          * stack will need rebasing, and we'll need to remove our work
6976          * areas each time
6977          */
6978  restart:
6979 #endif
6980
6981         amount = expdest - ((char *)stackblock() + resetloc);
6982         STADJUST(-amount, expdest);
6983         startp = (char *)stackblock() + startloc;
6984
6985         rmesc = startp;
6986         rmescend = (char *)stackblock() + strloc;
6987         //bb_error_msg("str7:'%s'", rmescend);
6988         if (quotes) {
6989 //TODO: how to handle slash_pos here if string changes (shortens?)
6990                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6991                 if (rmesc != startp) {
6992                         rmescend = expdest;
6993                         startp = (char *)stackblock() + startloc;
6994                 }
6995         }
6996         rmescend--;
6997         str = (char *)stackblock() + strloc;
6998         /*
6999          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7000          * The result is a_\_z_c (not a\_\_z_c)!
7001          *
7002          * The search pattern and replace string treat backslashes differently!
7003          * "&slash_pos" causes rmescapes() to work differently on the pattern
7004          * and string.  It's only used on the first call.
7005          */
7006         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7007         rmescapes(str, RMESCAPE_GLOB,
7008                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7009         );
7010
7011 #if BASH_PATTERN_SUBST
7012         workloc = expdest - (char *)stackblock();
7013         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7014                 int len;
7015                 char *idx, *end;
7016
7017                 if (!repl) {
7018                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7019                         repl = nullstr;
7020                         if (slash_pos >= 0) {
7021                                 repl = str + slash_pos;
7022                                 *repl++ = '\0';
7023                         }
7024                 }
7025                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7026
7027                 /* If there's no pattern to match, return the expansion unmolested */
7028                 if (str[0] == '\0')
7029                         return NULL;
7030
7031                 len = 0;
7032                 idx = startp;
7033                 end = str - 1;
7034                 while (idx < end) {
7035  try_to_match:
7036                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7037                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7038                         if (!loc) {
7039                                 /* No match, advance */
7040                                 char *restart_detect = stackblock();
7041  skip_matching:
7042                                 STPUTC(*idx, expdest);
7043                                 if (quotes && (unsigned char)*idx == CTLESC) {
7044                                         idx++;
7045                                         len++;
7046                                         STPUTC(*idx, expdest);
7047                                 }
7048                                 if (stackblock() != restart_detect)
7049                                         goto restart;
7050                                 idx++;
7051                                 len++;
7052                                 rmesc++;
7053                                 /* continue; - prone to quadratic behavior, smarter code: */
7054                                 if (idx >= end)
7055                                         break;
7056                                 if (str[0] == '*') {
7057                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7058                                          * it would never match "ong_string" etc, no point in trying.
7059                                          */
7060                                         goto skip_matching;
7061                                 }
7062                                 goto try_to_match;
7063                         }
7064
7065                         if (subtype == VSREPLACEALL) {
7066                                 while (idx < loc) {
7067                                         if (quotes && (unsigned char)*idx == CTLESC)
7068                                                 idx++;
7069                                         idx++;
7070                                         rmesc++;
7071                                 }
7072                         } else {
7073                                 idx = loc;
7074                         }
7075
7076                         //bb_error_msg("repl:'%s'", repl);
7077                         for (loc = (char*)repl; *loc; loc++) {
7078                                 char *restart_detect = stackblock();
7079                                 if (quotes && *loc == '\\') {
7080                                         STPUTC(CTLESC, expdest);
7081                                         len++;
7082                                 }
7083                                 STPUTC(*loc, expdest);
7084                                 if (stackblock() != restart_detect)
7085                                         goto restart;
7086                                 len++;
7087                         }
7088
7089                         if (subtype == VSREPLACE) {
7090                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7091                                 while (*idx) {
7092                                         char *restart_detect = stackblock();
7093                                         STPUTC(*idx, expdest);
7094                                         if (stackblock() != restart_detect)
7095                                                 goto restart;
7096                                         len++;
7097                                         idx++;
7098                                 }
7099                                 break;
7100                         }
7101                 }
7102
7103                 /* We've put the replaced text into a buffer at workloc, now
7104                  * move it to the right place and adjust the stack.
7105                  */
7106                 STPUTC('\0', expdest);
7107                 startp = (char *)stackblock() + startloc;
7108                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7109                 //bb_error_msg("startp:'%s'", startp);
7110                 amount = expdest - (startp + len);
7111                 STADJUST(-amount, expdest);
7112                 return startp;
7113         }
7114 #endif /* BASH_PATTERN_SUBST */
7115
7116         subtype -= VSTRIMRIGHT;
7117 #if DEBUG
7118         if (subtype < 0 || subtype > 7)
7119                 abort();
7120 #endif
7121         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7122         zero = subtype >> 1;
7123         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7124         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7125
7126         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7127         if (loc) {
7128                 if (zero) {
7129                         memmove(startp, loc, str - loc);
7130                         loc = startp + (str - loc) - 1;
7131                 }
7132                 *loc = '\0';
7133                 amount = loc - expdest;
7134                 STADJUST(amount, expdest);
7135         }
7136         return loc;
7137 }
7138
7139 /*
7140  * Add the value of a specialized variable to the stack string.
7141  * name parameter (examples):
7142  * ash -c 'echo $1'      name:'1='
7143  * ash -c 'echo $qwe'    name:'qwe='
7144  * ash -c 'echo $$'      name:'$='
7145  * ash -c 'echo ${$}'    name:'$='
7146  * ash -c 'echo ${$##q}' name:'$=q'
7147  * ash -c 'echo ${#$}'   name:'$='
7148  * note: examples with bad shell syntax:
7149  * ash -c 'echo ${#$1}'  name:'$=1'
7150  * ash -c 'echo ${#1#}'  name:'1=#'
7151  */
7152 static NOINLINE ssize_t
7153 varvalue(char *name, int varflags, int flags, int *quotedp)
7154 {
7155         const char *p;
7156         int num;
7157         int i;
7158         ssize_t len = 0;
7159         int sep;
7160         int quoted = *quotedp;
7161         int subtype = varflags & VSTYPE;
7162         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7163         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7164         int syntax;
7165
7166         sep = (flags & EXP_FULL) << CHAR_BIT;
7167         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7168
7169         switch (*name) {
7170         case '$':
7171                 num = rootpid;
7172                 goto numvar;
7173         case '?':
7174                 num = exitstatus;
7175                 goto numvar;
7176         case '#':
7177                 num = shellparam.nparam;
7178                 goto numvar;
7179         case '!':
7180                 num = backgndpid;
7181                 if (num == 0)
7182                         return -1;
7183  numvar:
7184                 len = cvtnum(num);
7185                 goto check_1char_name;
7186         case '-':
7187                 expdest = makestrspace(NOPTS, expdest);
7188                 for (i = NOPTS - 1; i >= 0; i--) {
7189                         if (optlist[i]) {
7190                                 USTPUTC(optletters(i), expdest);
7191                                 len++;
7192                         }
7193                 }
7194  check_1char_name:
7195 #if 0
7196                 /* handles cases similar to ${#$1} */
7197                 if (name[2] != '\0')
7198                         raise_error_syntax("bad substitution");
7199 #endif
7200                 break;
7201         case '@':
7202                 if (quoted && sep)
7203                         goto param;
7204                 /* fall through */
7205         case '*': {
7206                 char **ap;
7207                 char sepc;
7208
7209                 if (quoted)
7210                         sep = 0;
7211                 sep |= ifsset() ? ifsval()[0] : ' ';
7212  param:
7213                 sepc = sep;
7214                 *quotedp = !sepc;
7215                 ap = shellparam.p;
7216                 if (!ap)
7217                         return -1;
7218                 while ((p = *ap++) != NULL) {
7219                         len += strtodest(p, syntax, quotes);
7220
7221                         if (*ap && sep) {
7222                                 len++;
7223                                 memtodest(&sepc, 1, syntax, quotes);
7224                         }
7225                 }
7226                 break;
7227         } /* case '*' */
7228         case '0':
7229         case '1':
7230         case '2':
7231         case '3':
7232         case '4':
7233         case '5':
7234         case '6':
7235         case '7':
7236         case '8':
7237         case '9':
7238                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7239                 if (num < 0 || num > shellparam.nparam)
7240                         return -1;
7241                 p = num ? shellparam.p[num - 1] : arg0;
7242                 goto value;
7243         default:
7244                 /* NB: name has form "VAR=..." */
7245                 p = lookupvar(name);
7246  value:
7247                 if (!p)
7248                         return -1;
7249
7250                 len = strtodest(p, syntax, quotes);
7251 #if ENABLE_UNICODE_SUPPORT
7252                 if (subtype == VSLENGTH && len > 0) {
7253                         reinit_unicode_for_ash();
7254                         if (unicode_status == UNICODE_ON) {
7255                                 STADJUST(-len, expdest);
7256                                 discard = 0;
7257                                 len = unicode_strlen(p);
7258                         }
7259                 }
7260 #endif
7261                 break;
7262         }
7263
7264         if (discard)
7265                 STADJUST(-len, expdest);
7266         return len;
7267 }
7268
7269 /*
7270  * Expand a variable, and return a pointer to the next character in the
7271  * input string.
7272  */
7273 static char *
7274 evalvar(char *p, int flag)
7275 {
7276         char varflags;
7277         char subtype;
7278         int quoted;
7279         char easy;
7280         char *var;
7281         int patloc;
7282         int startloc;
7283         ssize_t varlen;
7284
7285         varflags = (unsigned char) *p++;
7286         subtype = varflags & VSTYPE;
7287
7288         if (!subtype)
7289                 raise_error_syntax("bad substitution");
7290
7291         quoted = flag & EXP_QUOTED;
7292         var = p;
7293         easy = (!quoted || (*var == '@' && shellparam.nparam));
7294         startloc = expdest - (char *)stackblock();
7295         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7296
7297  again:
7298         varlen = varvalue(var, varflags, flag, &quoted);
7299         if (varflags & VSNUL)
7300                 varlen--;
7301
7302         if (subtype == VSPLUS) {
7303                 varlen = -1 - varlen;
7304                 goto vsplus;
7305         }
7306
7307         if (subtype == VSMINUS) {
7308  vsplus:
7309                 if (varlen < 0) {
7310                         argstr(
7311                                 p,
7312                                 flag | EXP_TILDE | EXP_WORD
7313                         );
7314                         goto end;
7315                 }
7316                 goto record;
7317         }
7318
7319         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7320                 if (varlen >= 0)
7321                         goto record;
7322
7323                 subevalvar(p, var, 0, subtype, startloc, varflags,
7324                            flag & ~QUOTES_ESC);
7325                 varflags &= ~VSNUL;
7326                 /*
7327                  * Remove any recorded regions beyond
7328                  * start of variable
7329                  */
7330                 removerecordregions(startloc);
7331                 goto again;
7332         }
7333
7334         if (varlen < 0 && uflag)
7335                 varunset(p, var, 0, 0);
7336
7337         if (subtype == VSLENGTH) {
7338                 cvtnum(varlen > 0 ? varlen : 0);
7339                 goto record;
7340         }
7341
7342         if (subtype == VSNORMAL) {
7343  record:
7344                 if (!easy)
7345                         goto end;
7346                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7347                 goto end;
7348         }
7349
7350 #if DEBUG
7351         switch (subtype) {
7352         case VSTRIMLEFT:
7353         case VSTRIMLEFTMAX:
7354         case VSTRIMRIGHT:
7355         case VSTRIMRIGHTMAX:
7356 #if BASH_SUBSTR
7357         case VSSUBSTR:
7358 #endif
7359 #if BASH_PATTERN_SUBST
7360         case VSREPLACE:
7361         case VSREPLACEALL:
7362 #endif
7363                 break;
7364         default:
7365                 abort();
7366         }
7367 #endif
7368
7369         if (varlen >= 0) {
7370                 /*
7371                  * Terminate the string and start recording the pattern
7372                  * right after it
7373                  */
7374                 STPUTC('\0', expdest);
7375                 patloc = expdest - (char *)stackblock();
7376                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7377                                 startloc, varflags, flag)) {
7378                         int amount = expdest - (
7379                                 (char *)stackblock() + patloc - 1
7380                         );
7381                         STADJUST(-amount, expdest);
7382                 }
7383                 /* Remove any recorded regions beyond start of variable */
7384                 removerecordregions(startloc);
7385                 goto record;
7386         }
7387
7388  end:
7389         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7390                 int nesting = 1;
7391                 for (;;) {
7392                         unsigned char c = *p++;
7393                         if (c == CTLESC)
7394                                 p++;
7395                         else if (c == CTLBACKQ) {
7396                                 if (varlen >= 0)
7397                                         argbackq = argbackq->next;
7398                         } else if (c == CTLVAR) {
7399                                 if ((*p++ & VSTYPE) != VSNORMAL)
7400                                         nesting++;
7401                         } else if (c == CTLENDVAR) {
7402                                 if (--nesting == 0)
7403                                         break;
7404                         }
7405                 }
7406         }
7407         return p;
7408 }
7409
7410 /*
7411  * Add a file name to the list.
7412  */
7413 static void
7414 addfname(const char *name)
7415 {
7416         struct strlist *sp;
7417
7418         sp = stzalloc(sizeof(*sp));
7419         sp->text = sstrdup(name);
7420         *exparg.lastp = sp;
7421         exparg.lastp = &sp->next;
7422 }
7423
7424 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7425 static int
7426 hasmeta(const char *p)
7427 {
7428         static const char chars[] ALIGN1 = {
7429                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7430         };
7431
7432         for (;;) {
7433                 p = strpbrk(p, chars);
7434                 if (!p)
7435                         break;
7436                 switch ((unsigned char) *p) {
7437                 case CTLQUOTEMARK:
7438                         for (;;) {
7439                                 p++;
7440                                 if (*p == CTLQUOTEMARK)
7441                                         break;
7442                                 if (*p == CTLESC)
7443                                         p++;
7444                                 if (*p == '\0') /* huh? */
7445                                         return 0;
7446                         }
7447                         break;
7448                 case '\\':
7449                 case CTLESC:
7450                         p++;
7451                         if (*p == '\0')
7452                                 return 0;
7453                         break;
7454                 case '[':
7455                         if (!strchr(p + 1, ']')) {
7456                                 /* It's not a properly closed [] pattern,
7457                                  * but other metas may follow. Continue checking.
7458                                  * my[file* _is_ globbed by bash
7459                                  * and matches filenames like "my[file1".
7460                                  */
7461                                 break;
7462                         }
7463                         /* fallthrough */
7464                 default:
7465                 /* case '*': */
7466                 /* case '?': */
7467                         return 1;
7468                 }
7469                 p++;
7470         }
7471
7472         return 0;
7473 }
7474
7475 /* If we want to use glob() from libc... */
7476 #if !ENABLE_ASH_INTERNAL_GLOB
7477
7478 /* Add the result of glob() to the list */
7479 static void
7480 addglob(const glob_t *pglob)
7481 {
7482         char **p = pglob->gl_pathv;
7483
7484         do {
7485                 addfname(*p);
7486         } while (*++p);
7487 }
7488 static void
7489 expandmeta(struct strlist *str /*, int flag*/)
7490 {
7491         /* TODO - EXP_REDIR */
7492
7493         while (str) {
7494                 char *p;
7495                 glob_t pglob;
7496                 int i;
7497
7498                 if (fflag)
7499                         goto nometa;
7500
7501                 if (!hasmeta(str->text))
7502                         goto nometa;
7503
7504                 INT_OFF;
7505                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7506 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7507 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7508 //
7509 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7510 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7511 // Which means you need to unescape the string, right? Not so fast:
7512 // if there _is_ a file named "file\?" (with backslash), it is returned
7513 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7514 // You DON'T KNOW by looking at the result whether you need to unescape it.
7515 //
7516 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7517 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7518 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7519 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7520 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7521 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7522                 i = glob(p, 0, NULL, &pglob);
7523                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7524                 if (p != str->text)
7525                         free(p);
7526                 switch (i) {
7527                 case 0:
7528 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7529                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7530                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7531                                 goto nometa2;
7532 #endif
7533                         addglob(&pglob);
7534                         globfree(&pglob);
7535                         INT_ON;
7536                         break;
7537                 case GLOB_NOMATCH:
7538  //nometa2:
7539                         globfree(&pglob);
7540                         INT_ON;
7541  nometa:
7542                         *exparg.lastp = str;
7543                         rmescapes(str->text, 0, NULL);
7544                         exparg.lastp = &str->next;
7545                         break;
7546                 default:        /* GLOB_NOSPACE */
7547                         globfree(&pglob);
7548                         INT_ON;
7549                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7550                 }
7551                 str = str->next;
7552         }
7553 }
7554
7555 #else
7556 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7557
7558 /*
7559  * Do metacharacter (i.e. *, ?, [...]) expansion.
7560  */
7561 static void
7562 expmeta(char *expdir, char *enddir, char *name)
7563 {
7564         char *p;
7565         const char *cp;
7566         char *start;
7567         char *endname;
7568         int metaflag;
7569         struct stat statb;
7570         DIR *dirp;
7571         struct dirent *dp;
7572         int atend;
7573         int matchdot;
7574         int esc;
7575
7576         metaflag = 0;
7577         start = name;
7578         for (p = name; esc = 0, *p; p += esc + 1) {
7579                 if (*p == '*' || *p == '?')
7580                         metaflag = 1;
7581                 else if (*p == '[') {
7582                         char *q = p + 1;
7583                         if (*q == '!')
7584                                 q++;
7585                         for (;;) {
7586                                 if (*q == '\\')
7587                                         q++;
7588                                 if (*q == '/' || *q == '\0')
7589                                         break;
7590                                 if (*++q == ']') {
7591                                         metaflag = 1;
7592                                         break;
7593                                 }
7594                         }
7595                 } else {
7596                         if (*p == '\\')
7597                                 esc++;
7598                         if (p[esc] == '/') {
7599                                 if (metaflag)
7600                                         break;
7601                                 start = p + esc + 1;
7602                         }
7603                 }
7604         }
7605         if (metaflag == 0) {    /* we've reached the end of the file name */
7606                 if (enddir != expdir)
7607                         metaflag++;
7608                 p = name;
7609                 do {
7610                         if (*p == '\\')
7611                                 p++;
7612                         *enddir++ = *p;
7613                 } while (*p++);
7614                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7615                         addfname(expdir);
7616                 return;
7617         }
7618         endname = p;
7619         if (name < start) {
7620                 p = name;
7621                 do {
7622                         if (*p == '\\')
7623                                 p++;
7624                         *enddir++ = *p++;
7625                 } while (p < start);
7626         }
7627         if (enddir == expdir) {
7628                 cp = ".";
7629         } else if (enddir == expdir + 1 && *expdir == '/') {
7630                 cp = "/";
7631         } else {
7632                 cp = expdir;
7633                 enddir[-1] = '\0';
7634         }
7635         dirp = opendir(cp);
7636         if (dirp == NULL)
7637                 return;
7638         if (enddir != expdir)
7639                 enddir[-1] = '/';
7640         if (*endname == 0) {
7641                 atend = 1;
7642         } else {
7643                 atend = 0;
7644                 *endname = '\0';
7645                 endname += esc + 1;
7646         }
7647         matchdot = 0;
7648         p = start;
7649         if (*p == '\\')
7650                 p++;
7651         if (*p == '.')
7652                 matchdot++;
7653         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7654                 if (dp->d_name[0] == '.' && !matchdot)
7655                         continue;
7656                 if (pmatch(start, dp->d_name)) {
7657                         if (atend) {
7658                                 strcpy(enddir, dp->d_name);
7659                                 addfname(expdir);
7660                         } else {
7661                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7662                                         continue;
7663                                 p[-1] = '/';
7664                                 expmeta(expdir, p, endname);
7665                         }
7666                 }
7667         }
7668         closedir(dirp);
7669         if (!atend)
7670                 endname[-esc - 1] = esc ? '\\' : '/';
7671 }
7672
7673 static struct strlist *
7674 msort(struct strlist *list, int len)
7675 {
7676         struct strlist *p, *q = NULL;
7677         struct strlist **lpp;
7678         int half;
7679         int n;
7680
7681         if (len <= 1)
7682                 return list;
7683         half = len >> 1;
7684         p = list;
7685         for (n = half; --n >= 0;) {
7686                 q = p;
7687                 p = p->next;
7688         }
7689         q->next = NULL;                 /* terminate first half of list */
7690         q = msort(list, half);          /* sort first half of list */
7691         p = msort(p, len - half);               /* sort second half */
7692         lpp = &list;
7693         for (;;) {
7694 #if ENABLE_LOCALE_SUPPORT
7695                 if (strcoll(p->text, q->text) < 0)
7696 #else
7697                 if (strcmp(p->text, q->text) < 0)
7698 #endif
7699                                                 {
7700                         *lpp = p;
7701                         lpp = &p->next;
7702                         p = *lpp;
7703                         if (p == NULL) {
7704                                 *lpp = q;
7705                                 break;
7706                         }
7707                 } else {
7708                         *lpp = q;
7709                         lpp = &q->next;
7710                         q = *lpp;
7711                         if (q == NULL) {
7712                                 *lpp = p;
7713                                 break;
7714                         }
7715                 }
7716         }
7717         return list;
7718 }
7719
7720 /*
7721  * Sort the results of file name expansion.  It calculates the number of
7722  * strings to sort and then calls msort (short for merge sort) to do the
7723  * work.
7724  */
7725 static struct strlist *
7726 expsort(struct strlist *str)
7727 {
7728         int len;
7729         struct strlist *sp;
7730
7731         len = 0;
7732         for (sp = str; sp; sp = sp->next)
7733                 len++;
7734         return msort(str, len);
7735 }
7736
7737 static void
7738 expandmeta(struct strlist *str /*, int flag*/)
7739 {
7740         /* TODO - EXP_REDIR */
7741
7742         while (str) {
7743                 char *expdir;
7744                 struct strlist **savelastp;
7745                 struct strlist *sp;
7746                 char *p;
7747
7748                 if (fflag)
7749                         goto nometa;
7750                 if (!hasmeta(str->text))
7751                         goto nometa;
7752                 savelastp = exparg.lastp;
7753
7754                 INT_OFF;
7755                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7756                 {
7757                         int i = strlen(str->text);
7758 //BUGGY estimation of how long expanded name can be
7759                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7760                 }
7761                 expmeta(expdir, expdir, p);
7762                 free(expdir);
7763                 if (p != str->text)
7764                         free(p);
7765                 INT_ON;
7766                 if (exparg.lastp == savelastp) {
7767                         /*
7768                          * no matches
7769                          */
7770  nometa:
7771                         *exparg.lastp = str;
7772                         rmescapes(str->text, 0, NULL);
7773                         exparg.lastp = &str->next;
7774                 } else {
7775                         *exparg.lastp = NULL;
7776                         *savelastp = sp = expsort(*savelastp);
7777                         while (sp->next != NULL)
7778                                 sp = sp->next;
7779                         exparg.lastp = &sp->next;
7780                 }
7781                 str = str->next;
7782         }
7783 }
7784 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7785
7786 /*
7787  * Perform variable substitution and command substitution on an argument,
7788  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7789  * perform splitting and file name expansion.  When arglist is NULL, perform
7790  * here document expansion.
7791  */
7792 static void
7793 expandarg(union node *arg, struct arglist *arglist, int flag)
7794 {
7795         struct strlist *sp;
7796         char *p;
7797
7798         argbackq = arg->narg.backquote;
7799         STARTSTACKSTR(expdest);
7800         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7801         argstr(arg->narg.text, flag);
7802         p = _STPUTC('\0', expdest);
7803         expdest = p - 1;
7804         if (arglist == NULL) {
7805                 /* here document expanded */
7806                 goto out;
7807         }
7808         p = grabstackstr(p);
7809         TRACE(("expandarg: p:'%s'\n", p));
7810         exparg.lastp = &exparg.list;
7811         /*
7812          * TODO - EXP_REDIR
7813          */
7814         if (flag & EXP_FULL) {
7815                 ifsbreakup(p, &exparg);
7816                 *exparg.lastp = NULL;
7817                 exparg.lastp = &exparg.list;
7818                 expandmeta(exparg.list /*, flag*/);
7819         } else {
7820                 sp = stzalloc(sizeof(*sp));
7821                 sp->text = p;
7822                 *exparg.lastp = sp;
7823                 exparg.lastp = &sp->next;
7824         }
7825         *exparg.lastp = NULL;
7826         if (exparg.list) {
7827                 *arglist->lastp = exparg.list;
7828                 arglist->lastp = exparg.lastp;
7829         }
7830
7831  out:
7832         ifsfree();
7833 }
7834
7835 /*
7836  * Expand shell variables and backquotes inside a here document.
7837  */
7838 static void
7839 expandhere(union node *arg, int fd)
7840 {
7841         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7842         full_write(fd, stackblock(), expdest - (char *)stackblock());
7843 }
7844
7845 /*
7846  * Returns true if the pattern matches the string.
7847  */
7848 static int
7849 patmatch(char *pattern, const char *string)
7850 {
7851         char *p = preglob(pattern, 0);
7852         int r = pmatch(p, string);
7853         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7854         return r;
7855 }
7856
7857 /*
7858  * See if a pattern matches in a case statement.
7859  */
7860 static int
7861 casematch(union node *pattern, char *val)
7862 {
7863         struct stackmark smark;
7864         int result;
7865
7866         setstackmark(&smark);
7867         argbackq = pattern->narg.backquote;
7868         STARTSTACKSTR(expdest);
7869         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7870         STACKSTRNUL(expdest);
7871         ifsfree();
7872         result = patmatch(stackblock(), val);
7873         popstackmark(&smark);
7874         return result;
7875 }
7876
7877
7878 /* ============ find_command */
7879
7880 struct builtincmd {
7881         const char *name;
7882         int (*builtin)(int, char **) FAST_FUNC;
7883         /* unsigned flags; */
7884 };
7885 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7886 /* "regular" builtins always take precedence over commands,
7887  * regardless of PATH=....%builtin... position */
7888 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7889 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7890
7891 struct cmdentry {
7892         smallint cmdtype;       /* CMDxxx */
7893         union param {
7894                 int index;
7895                 /* index >= 0 for commands without path (slashes) */
7896                 /* (TODO: what exactly does the value mean? PATH position?) */
7897                 /* index == -1 for commands with slashes */
7898                 /* index == (-2 - applet_no) for NOFORK applets */
7899                 const struct builtincmd *cmd;
7900                 struct funcnode *func;
7901         } u;
7902 };
7903 /* values of cmdtype */
7904 #define CMDUNKNOWN      -1      /* no entry in table for command */
7905 #define CMDNORMAL       0       /* command is an executable program */
7906 #define CMDFUNCTION     1       /* command is a shell function */
7907 #define CMDBUILTIN      2       /* command is a shell builtin */
7908
7909 /* action to find_command() */
7910 #define DO_ERR          0x01    /* prints errors */
7911 #define DO_ABS          0x02    /* checks absolute paths */
7912 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7913 #define DO_ALTPATH      0x08    /* using alternate path */
7914 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7915
7916 static void find_command(char *, struct cmdentry *, int, const char *);
7917
7918
7919 /* ============ Hashing commands */
7920
7921 /*
7922  * When commands are first encountered, they are entered in a hash table.
7923  * This ensures that a full path search will not have to be done for them
7924  * on each invocation.
7925  *
7926  * We should investigate converting to a linear search, even though that
7927  * would make the command name "hash" a misnomer.
7928  */
7929
7930 struct tblentry {
7931         struct tblentry *next;  /* next entry in hash chain */
7932         union param param;      /* definition of builtin function */
7933         smallint cmdtype;       /* CMDxxx */
7934         char rehash;            /* if set, cd done since entry created */
7935         char cmdname[1];        /* name of command */
7936 };
7937
7938 static struct tblentry **cmdtable;
7939 #define INIT_G_cmdtable() do { \
7940         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7941 } while (0)
7942
7943 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7944
7945
7946 static void
7947 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7948 {
7949 #if ENABLE_FEATURE_SH_STANDALONE
7950         if (applet_no >= 0) {
7951                 if (APPLET_IS_NOEXEC(applet_no)) {
7952                         clearenv();
7953                         while (*envp)
7954                                 putenv(*envp++);
7955                         popredir(/*drop:*/ 1);
7956                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7957                 }
7958                 /* re-exec ourselves with the new arguments */
7959                 execve(bb_busybox_exec_path, argv, envp);
7960                 /* If they called chroot or otherwise made the binary no longer
7961                  * executable, fall through */
7962         }
7963 #endif
7964
7965  repeat:
7966 #ifdef SYSV
7967         do {
7968                 execve(cmd, argv, envp);
7969         } while (errno == EINTR);
7970 #else
7971         execve(cmd, argv, envp);
7972 #endif
7973         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7974                 /* Run "cmd" as a shell script:
7975                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7976                  * "If the execve() function fails with ENOEXEC, the shell
7977                  * shall execute a command equivalent to having a shell invoked
7978                  * with the command name as its first operand,
7979                  * with any remaining arguments passed to the new shell"
7980                  *
7981                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7982                  * just call ourselves.
7983                  *
7984                  * Note that bash reads ~80 chars of the file, and if it sees
7985                  * a zero byte before it sees newline, it doesn't try to
7986                  * interpret it, but fails with "cannot execute binary file"
7987                  * message and exit code 126. For one, this prevents attempts
7988                  * to interpret foreign ELF binaries as shell scripts.
7989                  */
7990                 argv[0] = (char*) cmd;
7991                 cmd = bb_busybox_exec_path;
7992                 /* NB: this is only possible because all callers of shellexec()
7993                  * ensure that the argv[-1] slot exists!
7994                  */
7995                 argv--;
7996                 argv[0] = (char*) "ash";
7997                 goto repeat;
7998         }
7999 }
8000
8001 /*
8002  * Exec a program.  Never returns.  If you change this routine, you may
8003  * have to change the find_command routine as well.
8004  * argv[-1] must exist and be writable! See tryexec() for why.
8005  */
8006 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8007 static void shellexec(char *prog, char **argv, const char *path, int idx)
8008 {
8009         char *cmdname;
8010         int e;
8011         char **envp;
8012         int exerrno;
8013         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8014
8015         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8016         if (strchr(prog, '/') != NULL
8017 #if ENABLE_FEATURE_SH_STANDALONE
8018          || (applet_no = find_applet_by_name(prog)) >= 0
8019 #endif
8020         ) {
8021                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8022                 if (applet_no >= 0) {
8023                         /* We tried execing ourself, but it didn't work.
8024                          * Maybe /proc/self/exe doesn't exist?
8025                          * Try $PATH search.
8026                          */
8027                         goto try_PATH;
8028                 }
8029                 e = errno;
8030         } else {
8031  try_PATH:
8032                 e = ENOENT;
8033                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8034                         if (--idx < 0 && pathopt == NULL) {
8035                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8036                                 if (errno != ENOENT && errno != ENOTDIR)
8037                                         e = errno;
8038                         }
8039                         stunalloc(cmdname);
8040                 }
8041         }
8042
8043         /* Map to POSIX errors */
8044         switch (e) {
8045         case EACCES:
8046                 exerrno = 126;
8047                 break;
8048         case ENOENT:
8049                 exerrno = 127;
8050                 break;
8051         default:
8052                 exerrno = 2;
8053                 break;
8054         }
8055         exitstatus = exerrno;
8056         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8057                 prog, e, suppress_int));
8058         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8059         /* NOTREACHED */
8060 }
8061
8062 static void
8063 printentry(struct tblentry *cmdp)
8064 {
8065         int idx;
8066         const char *path;
8067         char *name;
8068
8069         idx = cmdp->param.index;
8070         path = pathval();
8071         do {
8072                 name = path_advance(&path, cmdp->cmdname);
8073                 stunalloc(name);
8074         } while (--idx >= 0);
8075         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8076 }
8077
8078 /*
8079  * Clear out command entries.  The argument specifies the first entry in
8080  * PATH which has changed.
8081  */
8082 static void
8083 clearcmdentry(int firstchange)
8084 {
8085         struct tblentry **tblp;
8086         struct tblentry **pp;
8087         struct tblentry *cmdp;
8088
8089         INT_OFF;
8090         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8091                 pp = tblp;
8092                 while ((cmdp = *pp) != NULL) {
8093                         if ((cmdp->cmdtype == CMDNORMAL &&
8094                              cmdp->param.index >= firstchange)
8095                          || (cmdp->cmdtype == CMDBUILTIN &&
8096                              builtinloc >= firstchange)
8097                         ) {
8098                                 *pp = cmdp->next;
8099                                 free(cmdp);
8100                         } else {
8101                                 pp = &cmdp->next;
8102                         }
8103                 }
8104         }
8105         INT_ON;
8106 }
8107
8108 /*
8109  * Locate a command in the command hash table.  If "add" is nonzero,
8110  * add the command to the table if it is not already present.  The
8111  * variable "lastcmdentry" is set to point to the address of the link
8112  * pointing to the entry, so that delete_cmd_entry can delete the
8113  * entry.
8114  *
8115  * Interrupts must be off if called with add != 0.
8116  */
8117 static struct tblentry **lastcmdentry;
8118
8119 static struct tblentry *
8120 cmdlookup(const char *name, int add)
8121 {
8122         unsigned int hashval;
8123         const char *p;
8124         struct tblentry *cmdp;
8125         struct tblentry **pp;
8126
8127         p = name;
8128         hashval = (unsigned char)*p << 4;
8129         while (*p)
8130                 hashval += (unsigned char)*p++;
8131         hashval &= 0x7FFF;
8132         pp = &cmdtable[hashval % CMDTABLESIZE];
8133         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8134                 if (strcmp(cmdp->cmdname, name) == 0)
8135                         break;
8136                 pp = &cmdp->next;
8137         }
8138         if (add && cmdp == NULL) {
8139                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8140                                 + strlen(name)
8141                                 /* + 1 - already done because
8142                                  * tblentry::cmdname is char[1] */);
8143                 /*cmdp->next = NULL; - ckzalloc did it */
8144                 cmdp->cmdtype = CMDUNKNOWN;
8145                 strcpy(cmdp->cmdname, name);
8146         }
8147         lastcmdentry = pp;
8148         return cmdp;
8149 }
8150
8151 /*
8152  * Delete the command entry returned on the last lookup.
8153  */
8154 static void
8155 delete_cmd_entry(void)
8156 {
8157         struct tblentry *cmdp;
8158
8159         INT_OFF;
8160         cmdp = *lastcmdentry;
8161         *lastcmdentry = cmdp->next;
8162         if (cmdp->cmdtype == CMDFUNCTION)
8163                 freefunc(cmdp->param.func);
8164         free(cmdp);
8165         INT_ON;
8166 }
8167
8168 /*
8169  * Add a new command entry, replacing any existing command entry for
8170  * the same name - except special builtins.
8171  */
8172 static void
8173 addcmdentry(char *name, struct cmdentry *entry)
8174 {
8175         struct tblentry *cmdp;
8176
8177         cmdp = cmdlookup(name, 1);
8178         if (cmdp->cmdtype == CMDFUNCTION) {
8179                 freefunc(cmdp->param.func);
8180         }
8181         cmdp->cmdtype = entry->cmdtype;
8182         cmdp->param = entry->u;
8183         cmdp->rehash = 0;
8184 }
8185
8186 static int FAST_FUNC
8187 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8188 {
8189         struct tblentry **pp;
8190         struct tblentry *cmdp;
8191         int c;
8192         struct cmdentry entry;
8193         char *name;
8194
8195         if (nextopt("r") != '\0') {
8196                 clearcmdentry(0);
8197                 return 0;
8198         }
8199
8200         if (*argptr == NULL) {
8201                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8202                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8203                                 if (cmdp->cmdtype == CMDNORMAL)
8204                                         printentry(cmdp);
8205                         }
8206                 }
8207                 return 0;
8208         }
8209
8210         c = 0;
8211         while ((name = *argptr) != NULL) {
8212                 cmdp = cmdlookup(name, 0);
8213                 if (cmdp != NULL
8214                  && (cmdp->cmdtype == CMDNORMAL
8215                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8216                 ) {
8217                         delete_cmd_entry();
8218                 }
8219                 find_command(name, &entry, DO_ERR, pathval());
8220                 if (entry.cmdtype == CMDUNKNOWN)
8221                         c = 1;
8222                 argptr++;
8223         }
8224         return c;
8225 }
8226
8227 /*
8228  * Called when a cd is done.  Marks all commands so the next time they
8229  * are executed they will be rehashed.
8230  */
8231 static void
8232 hashcd(void)
8233 {
8234         struct tblentry **pp;
8235         struct tblentry *cmdp;
8236
8237         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8238                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8239                         if (cmdp->cmdtype == CMDNORMAL
8240                          || (cmdp->cmdtype == CMDBUILTIN
8241                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8242                              && builtinloc > 0)
8243                         ) {
8244                                 cmdp->rehash = 1;
8245                         }
8246                 }
8247         }
8248 }
8249
8250 /*
8251  * Fix command hash table when PATH changed.
8252  * Called before PATH is changed.  The argument is the new value of PATH;
8253  * pathval() still returns the old value at this point.
8254  * Called with interrupts off.
8255  */
8256 static void FAST_FUNC
8257 changepath(const char *new)
8258 {
8259         const char *old;
8260         int firstchange;
8261         int idx;
8262         int idx_bltin;
8263
8264         old = pathval();
8265         firstchange = 9999;     /* assume no change */
8266         idx = 0;
8267         idx_bltin = -1;
8268         for (;;) {
8269                 if (*old != *new) {
8270                         firstchange = idx;
8271                         if ((*old == '\0' && *new == ':')
8272                          || (*old == ':' && *new == '\0')
8273                         ) {
8274                                 firstchange++;
8275                         }
8276                         old = new;      /* ignore subsequent differences */
8277                 }
8278                 if (*new == '\0')
8279                         break;
8280                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8281                         idx_bltin = idx;
8282                 if (*new == ':')
8283                         idx++;
8284                 new++;
8285                 old++;
8286         }
8287         if (builtinloc < 0 && idx_bltin >= 0)
8288                 builtinloc = idx_bltin;             /* zap builtins */
8289         if (builtinloc >= 0 && idx_bltin < 0)
8290                 firstchange = 0;
8291         clearcmdentry(firstchange);
8292         builtinloc = idx_bltin;
8293 }
8294 enum {
8295         TEOF,
8296         TNL,
8297         TREDIR,
8298         TWORD,
8299         TSEMI,
8300         TBACKGND,
8301         TAND,
8302         TOR,
8303         TPIPE,
8304         TLP,
8305         TRP,
8306         TENDCASE,
8307         TENDBQUOTE,
8308         TNOT,
8309         TCASE,
8310         TDO,
8311         TDONE,
8312         TELIF,
8313         TELSE,
8314         TESAC,
8315         TFI,
8316         TFOR,
8317 #if BASH_FUNCTION
8318         TFUNCTION,
8319 #endif
8320         TIF,
8321         TIN,
8322         TTHEN,
8323         TUNTIL,
8324         TWHILE,
8325         TBEGIN,
8326         TEND
8327 };
8328 typedef smallint token_id_t;
8329
8330 /* Nth bit indicates if token marks the end of a list */
8331 enum {
8332         tokendlist = 0
8333         /*  0 */ | (1u << TEOF)
8334         /*  1 */ | (0u << TNL)
8335         /*  2 */ | (0u << TREDIR)
8336         /*  3 */ | (0u << TWORD)
8337         /*  4 */ | (0u << TSEMI)
8338         /*  5 */ | (0u << TBACKGND)
8339         /*  6 */ | (0u << TAND)
8340         /*  7 */ | (0u << TOR)
8341         /*  8 */ | (0u << TPIPE)
8342         /*  9 */ | (0u << TLP)
8343         /* 10 */ | (1u << TRP)
8344         /* 11 */ | (1u << TENDCASE)
8345         /* 12 */ | (1u << TENDBQUOTE)
8346         /* 13 */ | (0u << TNOT)
8347         /* 14 */ | (0u << TCASE)
8348         /* 15 */ | (1u << TDO)
8349         /* 16 */ | (1u << TDONE)
8350         /* 17 */ | (1u << TELIF)
8351         /* 18 */ | (1u << TELSE)
8352         /* 19 */ | (1u << TESAC)
8353         /* 20 */ | (1u << TFI)
8354         /* 21 */ | (0u << TFOR)
8355 #if BASH_FUNCTION
8356         /* 22 */ | (0u << TFUNCTION)
8357 #endif
8358         /* 23 */ | (0u << TIF)
8359         /* 24 */ | (0u << TIN)
8360         /* 25 */ | (1u << TTHEN)
8361         /* 26 */ | (0u << TUNTIL)
8362         /* 27 */ | (0u << TWHILE)
8363         /* 28 */ | (0u << TBEGIN)
8364         /* 29 */ | (1u << TEND)
8365         , /* thus far 29 bits used */
8366 };
8367
8368 static const char *const tokname_array[] = {
8369         "end of file",
8370         "newline",
8371         "redirection",
8372         "word",
8373         ";",
8374         "&",
8375         "&&",
8376         "||",
8377         "|",
8378         "(",
8379         ")",
8380         ";;",
8381         "`",
8382 #define KWDOFFSET 13
8383         /* the following are keywords */
8384         "!",
8385         "case",
8386         "do",
8387         "done",
8388         "elif",
8389         "else",
8390         "esac",
8391         "fi",
8392         "for",
8393 #if BASH_FUNCTION
8394         "function",
8395 #endif
8396         "if",
8397         "in",
8398         "then",
8399         "until",
8400         "while",
8401         "{",
8402         "}",
8403 };
8404
8405 /* Wrapper around strcmp for qsort/bsearch/... */
8406 static int
8407 pstrcmp(const void *a, const void *b)
8408 {
8409         return strcmp((char*)a, *(char**)b);
8410 }
8411
8412 static const char *const *
8413 findkwd(const char *s)
8414 {
8415         return bsearch(s, tokname_array + KWDOFFSET,
8416                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8417                         sizeof(tokname_array[0]), pstrcmp);
8418 }
8419
8420 /*
8421  * Locate and print what a word is...
8422  */
8423 static int
8424 describe_command(char *command, const char *path, int describe_command_verbose)
8425 {
8426         struct cmdentry entry;
8427 #if ENABLE_ASH_ALIAS
8428         const struct alias *ap;
8429 #endif
8430
8431         path = path ? path : pathval();
8432
8433         if (describe_command_verbose) {
8434                 out1str(command);
8435         }
8436
8437         /* First look at the keywords */
8438         if (findkwd(command)) {
8439                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8440                 goto out;
8441         }
8442
8443 #if ENABLE_ASH_ALIAS
8444         /* Then look at the aliases */
8445         ap = lookupalias(command, 0);
8446         if (ap != NULL) {
8447                 if (!describe_command_verbose) {
8448                         out1str("alias ");
8449                         printalias(ap);
8450                         return 0;
8451                 }
8452                 out1fmt(" is an alias for %s", ap->val);
8453                 goto out;
8454         }
8455 #endif
8456         /* Brute force */
8457         find_command(command, &entry, DO_ABS, path);
8458
8459         switch (entry.cmdtype) {
8460         case CMDNORMAL: {
8461                 int j = entry.u.index;
8462                 char *p;
8463                 if (j < 0) {
8464                         p = command;
8465                 } else {
8466                         do {
8467                                 p = path_advance(&path, command);
8468                                 stunalloc(p);
8469                         } while (--j >= 0);
8470                 }
8471                 if (describe_command_verbose) {
8472                         out1fmt(" is %s", p);
8473                 } else {
8474                         out1str(p);
8475                 }
8476                 break;
8477         }
8478
8479         case CMDFUNCTION:
8480                 if (describe_command_verbose) {
8481                         out1str(" is a shell function");
8482                 } else {
8483                         out1str(command);
8484                 }
8485                 break;
8486
8487         case CMDBUILTIN:
8488                 if (describe_command_verbose) {
8489                         out1fmt(" is a %sshell builtin",
8490                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8491                                         "special " : nullstr
8492                         );
8493                 } else {
8494                         out1str(command);
8495                 }
8496                 break;
8497
8498         default:
8499                 if (describe_command_verbose) {
8500                         out1str(": not found\n");
8501                 }
8502                 return 127;
8503         }
8504  out:
8505         out1str("\n");
8506         return 0;
8507 }
8508
8509 static int FAST_FUNC
8510 typecmd(int argc UNUSED_PARAM, char **argv)
8511 {
8512         int i = 1;
8513         int err = 0;
8514         int verbose = 1;
8515
8516         /* type -p ... ? (we don't bother checking for 'p') */
8517         if (argv[1] && argv[1][0] == '-') {
8518                 i++;
8519                 verbose = 0;
8520         }
8521         while (argv[i]) {
8522                 err |= describe_command(argv[i++], NULL, verbose);
8523         }
8524         return err;
8525 }
8526
8527 #if ENABLE_ASH_CMDCMD
8528 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8529 static char **
8530 parse_command_args(char **argv, const char **path)
8531 {
8532         char *cp, c;
8533
8534         for (;;) {
8535                 cp = *++argv;
8536                 if (!cp)
8537                         return NULL;
8538                 if (*cp++ != '-')
8539                         break;
8540                 c = *cp++;
8541                 if (!c)
8542                         break;
8543                 if (c == '-' && !*cp) {
8544                         if (!*++argv)
8545                                 return NULL;
8546                         break;
8547                 }
8548                 do {
8549                         switch (c) {
8550                         case 'p':
8551                                 *path = bb_default_path;
8552                                 break;
8553                         default:
8554                                 /* run 'typecmd' for other options */
8555                                 return NULL;
8556                         }
8557                         c = *cp++;
8558                 } while (c);
8559         }
8560         return argv;
8561 }
8562
8563 static int FAST_FUNC
8564 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8565 {
8566         char *cmd;
8567         int c;
8568         enum {
8569                 VERIFY_BRIEF = 1,
8570                 VERIFY_VERBOSE = 2,
8571         } verify = 0;
8572         const char *path = NULL;
8573
8574         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8575          * never reaches this function.
8576          */
8577
8578         while ((c = nextopt("pvV")) != '\0')
8579                 if (c == 'V')
8580                         verify |= VERIFY_VERBOSE;
8581                 else if (c == 'v')
8582                         /*verify |= VERIFY_BRIEF*/;
8583 #if DEBUG
8584                 else if (c != 'p')
8585                         abort();
8586 #endif
8587                 else
8588                         path = bb_default_path;
8589
8590         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8591         cmd = *argptr;
8592         if (/*verify && */ cmd)
8593                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8594
8595         return 0;
8596 }
8597 #endif
8598
8599
8600 /*static int funcblocksize;     // size of structures in function */
8601 /*static int funcstringsize;    // size of strings in node */
8602 static void *funcblock;         /* block to allocate function from */
8603 static char *funcstring_end;    /* end of block to allocate strings from */
8604
8605 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8606         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8607         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8608         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8609         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8610         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8611         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8612         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8613         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8614         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8615         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8616         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8617         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8618         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8619         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8620         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8621         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8622         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8623 #if BASH_REDIR_OUTPUT
8624         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8625 #endif
8626         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8627         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8628         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8629         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8630         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8631         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8632         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8633         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8634         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8635 };
8636
8637 static int calcsize(int funcblocksize, union node *n);
8638
8639 static int
8640 sizenodelist(int funcblocksize, struct nodelist *lp)
8641 {
8642         while (lp) {
8643                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8644                 funcblocksize = calcsize(funcblocksize, lp->n);
8645                 lp = lp->next;
8646         }
8647         return funcblocksize;
8648 }
8649
8650 static int
8651 calcsize(int funcblocksize, union node *n)
8652 {
8653         if (n == NULL)
8654                 return funcblocksize;
8655         funcblocksize += nodesize[n->type];
8656         switch (n->type) {
8657         case NCMD:
8658                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8659                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8660                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8661                 break;
8662         case NPIPE:
8663                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8664                 break;
8665         case NREDIR:
8666         case NBACKGND:
8667         case NSUBSHELL:
8668                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8669                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8670                 break;
8671         case NAND:
8672         case NOR:
8673         case NSEMI:
8674         case NWHILE:
8675         case NUNTIL:
8676                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8677                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8678                 break;
8679         case NIF:
8680                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8681                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8682                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8683                 break;
8684         case NFOR:
8685                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8686                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8687                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8688                 break;
8689         case NCASE:
8690                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8691                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8692                 break;
8693         case NCLIST:
8694                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8695                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8696                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8697                 break;
8698         case NDEFUN:
8699                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8700                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8701                 break;
8702         case NARG:
8703                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8704                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8705                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8706                 break;
8707         case NTO:
8708 #if BASH_REDIR_OUTPUT
8709         case NTO2:
8710 #endif
8711         case NCLOBBER:
8712         case NFROM:
8713         case NFROMTO:
8714         case NAPPEND:
8715                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8716                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8717                 break;
8718         case NTOFD:
8719         case NFROMFD:
8720                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8721                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8722         break;
8723         case NHERE:
8724         case NXHERE:
8725                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8726                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8727                 break;
8728         case NNOT:
8729                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8730                 break;
8731         };
8732         return funcblocksize;
8733 }
8734
8735 static char *
8736 nodeckstrdup(char *s)
8737 {
8738         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8739         return strcpy(funcstring_end, s);
8740 }
8741
8742 static union node *copynode(union node *);
8743
8744 static struct nodelist *
8745 copynodelist(struct nodelist *lp)
8746 {
8747         struct nodelist *start;
8748         struct nodelist **lpp;
8749
8750         lpp = &start;
8751         while (lp) {
8752                 *lpp = funcblock;
8753                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8754                 (*lpp)->n = copynode(lp->n);
8755                 lp = lp->next;
8756                 lpp = &(*lpp)->next;
8757         }
8758         *lpp = NULL;
8759         return start;
8760 }
8761
8762 static union node *
8763 copynode(union node *n)
8764 {
8765         union node *new;
8766
8767         if (n == NULL)
8768                 return NULL;
8769         new = funcblock;
8770         funcblock = (char *) funcblock + nodesize[n->type];
8771
8772         switch (n->type) {
8773         case NCMD:
8774                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8775                 new->ncmd.args = copynode(n->ncmd.args);
8776                 new->ncmd.assign = copynode(n->ncmd.assign);
8777                 new->ncmd.linno = n->ncmd.linno;
8778                 break;
8779         case NPIPE:
8780                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8781                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8782                 break;
8783         case NREDIR:
8784         case NBACKGND:
8785         case NSUBSHELL:
8786                 new->nredir.redirect = copynode(n->nredir.redirect);
8787                 new->nredir.n = copynode(n->nredir.n);
8788                 new->nredir.linno = n->nredir.linno;
8789                 break;
8790         case NAND:
8791         case NOR:
8792         case NSEMI:
8793         case NWHILE:
8794         case NUNTIL:
8795                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8796                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8797                 break;
8798         case NIF:
8799                 new->nif.elsepart = copynode(n->nif.elsepart);
8800                 new->nif.ifpart = copynode(n->nif.ifpart);
8801                 new->nif.test = copynode(n->nif.test);
8802                 break;
8803         case NFOR:
8804                 new->nfor.var = nodeckstrdup(n->nfor.var);
8805                 new->nfor.body = copynode(n->nfor.body);
8806                 new->nfor.args = copynode(n->nfor.args);
8807                 new->nfor.linno = n->nfor.linno;
8808                 break;
8809         case NCASE:
8810                 new->ncase.cases = copynode(n->ncase.cases);
8811                 new->ncase.expr = copynode(n->ncase.expr);
8812                 new->ncase.linno = n->ncase.linno;
8813                 break;
8814         case NCLIST:
8815                 new->nclist.body = copynode(n->nclist.body);
8816                 new->nclist.pattern = copynode(n->nclist.pattern);
8817                 new->nclist.next = copynode(n->nclist.next);
8818                 break;
8819         case NDEFUN:
8820                 new->ndefun.body = copynode(n->ndefun.body);
8821                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8822                 new->ndefun.linno = n->ndefun.linno;
8823                 break;
8824         case NARG:
8825                 new->narg.backquote = copynodelist(n->narg.backquote);
8826                 new->narg.text = nodeckstrdup(n->narg.text);
8827                 new->narg.next = copynode(n->narg.next);
8828                 break;
8829         case NTO:
8830 #if BASH_REDIR_OUTPUT
8831         case NTO2:
8832 #endif
8833         case NCLOBBER:
8834         case NFROM:
8835         case NFROMTO:
8836         case NAPPEND:
8837                 new->nfile.fname = copynode(n->nfile.fname);
8838                 new->nfile.fd = n->nfile.fd;
8839                 new->nfile.next = copynode(n->nfile.next);
8840                 break;
8841         case NTOFD:
8842         case NFROMFD:
8843                 new->ndup.vname = copynode(n->ndup.vname);
8844                 new->ndup.dupfd = n->ndup.dupfd;
8845                 new->ndup.fd = n->ndup.fd;
8846                 new->ndup.next = copynode(n->ndup.next);
8847                 break;
8848         case NHERE:
8849         case NXHERE:
8850                 new->nhere.doc = copynode(n->nhere.doc);
8851                 new->nhere.fd = n->nhere.fd;
8852                 new->nhere.next = copynode(n->nhere.next);
8853                 break;
8854         case NNOT:
8855                 new->nnot.com = copynode(n->nnot.com);
8856                 break;
8857         };
8858         new->type = n->type;
8859         return new;
8860 }
8861
8862 /*
8863  * Make a copy of a parse tree.
8864  */
8865 static struct funcnode *
8866 copyfunc(union node *n)
8867 {
8868         struct funcnode *f;
8869         size_t blocksize;
8870
8871         /*funcstringsize = 0;*/
8872         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8873         f = ckzalloc(blocksize /* + funcstringsize */);
8874         funcblock = (char *) f + offsetof(struct funcnode, n);
8875         funcstring_end = (char *) f + blocksize;
8876         copynode(n);
8877         /* f->count = 0; - ckzalloc did it */
8878         return f;
8879 }
8880
8881 /*
8882  * Define a shell function.
8883  */
8884 static void
8885 defun(union node *func)
8886 {
8887         struct cmdentry entry;
8888
8889         INT_OFF;
8890         entry.cmdtype = CMDFUNCTION;
8891         entry.u.func = copyfunc(func);
8892         addcmdentry(func->ndefun.text, &entry);
8893         INT_ON;
8894 }
8895
8896 /* Reasons for skipping commands (see comment on breakcmd routine) */
8897 #define SKIPBREAK      (1 << 0)
8898 #define SKIPCONT       (1 << 1)
8899 #define SKIPFUNC       (1 << 2)
8900 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8901 static int skipcount;           /* number of levels to skip */
8902 static int loopnest;            /* current loop nesting level */
8903 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8904
8905 /* Forward decl way out to parsing code - dotrap needs it */
8906 static int evalstring(char *s, int flags);
8907
8908 /* Called to execute a trap.
8909  * Single callsite - at the end of evaltree().
8910  * If we return non-zero, evaltree raises EXEXIT exception.
8911  *
8912  * Perhaps we should avoid entering new trap handlers
8913  * while we are executing a trap handler. [is it a TODO?]
8914  */
8915 static void
8916 dotrap(void)
8917 {
8918         uint8_t *g;
8919         int sig;
8920         uint8_t last_status;
8921
8922         if (!pending_sig)
8923                 return;
8924
8925         last_status = exitstatus;
8926         pending_sig = 0;
8927         barrier();
8928
8929         TRACE(("dotrap entered\n"));
8930         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8931                 char *p;
8932
8933                 if (!*g)
8934                         continue;
8935
8936                 if (evalskip) {
8937                         pending_sig = sig;
8938                         break;
8939                 }
8940
8941                 p = trap[sig];
8942                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8943                  * don't upset it by resetting gotsig[SIGINT-1] */
8944                 if (sig == SIGINT && !p)
8945                         continue;
8946
8947                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8948                 *g = 0;
8949                 if (!p)
8950                         continue;
8951                 evalstring(p, 0);
8952         }
8953         exitstatus = last_status;
8954         TRACE(("dotrap returns\n"));
8955 }
8956
8957 /* forward declarations - evaluation is fairly recursive business... */
8958 static int evalloop(union node *, int);
8959 static int evalfor(union node *, int);
8960 static int evalcase(union node *, int);
8961 static int evalsubshell(union node *, int);
8962 static void expredir(union node *);
8963 static int evalpipe(union node *, int);
8964 static int evalcommand(union node *, int);
8965 static int evalbltin(const struct builtincmd *, int, char **, int);
8966 static void prehash(union node *);
8967
8968 /*
8969  * Evaluate a parse tree.  The value is left in the global variable
8970  * exitstatus.
8971  */
8972 static int
8973 evaltree(union node *n, int flags)
8974 {
8975         int checkexit = 0;
8976         int (*evalfn)(union node *, int);
8977         int status = 0;
8978
8979         if (n == NULL) {
8980                 TRACE(("evaltree(NULL) called\n"));
8981                 goto out;
8982         }
8983         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8984
8985         dotrap();
8986
8987         switch (n->type) {
8988         default:
8989 #if DEBUG
8990                 out1fmt("Node type = %d\n", n->type);
8991                 fflush_all();
8992                 break;
8993 #endif
8994         case NNOT:
8995                 status = !evaltree(n->nnot.com, EV_TESTED);
8996                 goto setstatus;
8997         case NREDIR:
8998                 errlinno = lineno = n->nredir.linno;
8999                 if (funcline)
9000                         lineno -= funcline - 1;
9001                 expredir(n->nredir.redirect);
9002                 pushredir(n->nredir.redirect);
9003                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9004                 if (!status) {
9005                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9006                 }
9007                 if (n->nredir.redirect)
9008                         popredir(/*drop:*/ 0);
9009                 goto setstatus;
9010         case NCMD:
9011                 evalfn = evalcommand;
9012  checkexit:
9013                 if (eflag && !(flags & EV_TESTED))
9014                         checkexit = ~0;
9015                 goto calleval;
9016         case NFOR:
9017                 evalfn = evalfor;
9018                 goto calleval;
9019         case NWHILE:
9020         case NUNTIL:
9021                 evalfn = evalloop;
9022                 goto calleval;
9023         case NSUBSHELL:
9024         case NBACKGND:
9025                 evalfn = evalsubshell;
9026                 goto checkexit;
9027         case NPIPE:
9028                 evalfn = evalpipe;
9029                 goto checkexit;
9030         case NCASE:
9031                 evalfn = evalcase;
9032                 goto calleval;
9033         case NAND:
9034         case NOR:
9035         case NSEMI: {
9036
9037 #if NAND + 1 != NOR
9038 #error NAND + 1 != NOR
9039 #endif
9040 #if NOR + 1 != NSEMI
9041 #error NOR + 1 != NSEMI
9042 #endif
9043                 unsigned is_or = n->type - NAND;
9044                 status = evaltree(
9045                         n->nbinary.ch1,
9046                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9047                 );
9048                 if ((!status) == is_or || evalskip)
9049                         break;
9050                 n = n->nbinary.ch2;
9051  evaln:
9052                 evalfn = evaltree;
9053  calleval:
9054                 status = evalfn(n, flags);
9055                 goto setstatus;
9056         }
9057         case NIF:
9058                 status = evaltree(n->nif.test, EV_TESTED);
9059                 if (evalskip)
9060                         break;
9061                 if (!status) {
9062                         n = n->nif.ifpart;
9063                         goto evaln;
9064                 }
9065                 if (n->nif.elsepart) {
9066                         n = n->nif.elsepart;
9067                         goto evaln;
9068                 }
9069                 status = 0;
9070                 goto setstatus;
9071         case NDEFUN:
9072                 defun(n);
9073                 /* Not necessary. To test it:
9074                  * "false; f() { qwerty; }; echo $?" should print 0.
9075                  */
9076                 /* status = 0; */
9077  setstatus:
9078                 exitstatus = status;
9079                 break;
9080         }
9081  out:
9082         /* Order of checks below is important:
9083          * signal handlers trigger before exit caused by "set -e".
9084          */
9085         dotrap();
9086
9087         if (checkexit & status)
9088                 raise_exception(EXEXIT);
9089         if (flags & EV_EXIT)
9090                 raise_exception(EXEXIT);
9091
9092         TRACE(("leaving evaltree (no interrupts)\n"));
9093         return exitstatus;
9094 }
9095
9096 static int
9097 skiploop(void)
9098 {
9099         int skip = evalskip;
9100
9101         switch (skip) {
9102         case 0:
9103                 break;
9104         case SKIPBREAK:
9105         case SKIPCONT:
9106                 if (--skipcount <= 0) {
9107                         evalskip = 0;
9108                         break;
9109                 }
9110                 skip = SKIPBREAK;
9111                 break;
9112         }
9113         return skip;
9114 }
9115
9116 static int
9117 evalloop(union node *n, int flags)
9118 {
9119         int skip;
9120         int status;
9121
9122         loopnest++;
9123         status = 0;
9124         flags &= EV_TESTED;
9125         do {
9126                 int i;
9127
9128                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9129                 skip = skiploop();
9130                 if (skip == SKIPFUNC)
9131                         status = i;
9132                 if (skip)
9133                         continue;
9134                 if (n->type != NWHILE)
9135                         i = !i;
9136                 if (i != 0)
9137                         break;
9138                 status = evaltree(n->nbinary.ch2, flags);
9139                 skip = skiploop();
9140         } while (!(skip & ~SKIPCONT));
9141         loopnest--;
9142
9143         return status;
9144 }
9145
9146 static int
9147 evalfor(union node *n, int flags)
9148 {
9149         struct arglist arglist;
9150         union node *argp;
9151         struct strlist *sp;
9152         struct stackmark smark;
9153         int status = 0;
9154
9155         errlinno = lineno = n->ncase.linno;
9156         if (funcline)
9157                 lineno -= funcline - 1;
9158
9159         setstackmark(&smark);
9160         arglist.list = NULL;
9161         arglist.lastp = &arglist.list;
9162         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9163                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9164         }
9165         *arglist.lastp = NULL;
9166
9167         loopnest++;
9168         flags &= EV_TESTED;
9169         for (sp = arglist.list; sp; sp = sp->next) {
9170                 setvar0(n->nfor.var, sp->text);
9171                 status = evaltree(n->nfor.body, flags);
9172                 if (skiploop() & ~SKIPCONT)
9173                         break;
9174         }
9175         loopnest--;
9176         popstackmark(&smark);
9177
9178         return status;
9179 }
9180
9181 static int
9182 evalcase(union node *n, int flags)
9183 {
9184         union node *cp;
9185         union node *patp;
9186         struct arglist arglist;
9187         struct stackmark smark;
9188         int status = 0;
9189
9190         errlinno = lineno = n->ncase.linno;
9191         if (funcline)
9192                 lineno -= funcline - 1;
9193
9194         setstackmark(&smark);
9195         arglist.list = NULL;
9196         arglist.lastp = &arglist.list;
9197         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9198         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9199                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9200                         if (casematch(patp, arglist.list->text)) {
9201                                 /* Ensure body is non-empty as otherwise
9202                                  * EV_EXIT may prevent us from setting the
9203                                  * exit status.
9204                                  */
9205                                 if (evalskip == 0 && cp->nclist.body) {
9206                                         status = evaltree(cp->nclist.body, flags);
9207                                 }
9208                                 goto out;
9209                         }
9210                 }
9211         }
9212  out:
9213         popstackmark(&smark);
9214
9215         return status;
9216 }
9217
9218 /*
9219  * Kick off a subshell to evaluate a tree.
9220  */
9221 static int
9222 evalsubshell(union node *n, int flags)
9223 {
9224         struct job *jp;
9225         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9226         int status;
9227
9228         errlinno = lineno = n->nredir.linno;
9229         if (funcline)
9230                 lineno -= funcline - 1;
9231
9232         expredir(n->nredir.redirect);
9233         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9234                 goto nofork;
9235         INT_OFF;
9236         if (backgnd == FORK_FG)
9237                 get_tty_state();
9238         jp = makejob(/*n,*/ 1);
9239         if (forkshell(jp, n, backgnd) == 0) {
9240                 /* child */
9241                 INT_ON;
9242                 flags |= EV_EXIT;
9243                 if (backgnd)
9244                         flags &= ~EV_TESTED;
9245  nofork:
9246                 redirect(n->nredir.redirect, 0);
9247                 evaltreenr(n->nredir.n, flags);
9248                 /* never returns */
9249         }
9250         /* parent */
9251         status = 0;
9252         if (backgnd == FORK_FG)
9253                 status = waitforjob(jp);
9254         INT_ON;
9255         return status;
9256 }
9257
9258 /*
9259  * Compute the names of the files in a redirection list.
9260  */
9261 static void fixredir(union node *, const char *, int);
9262 static void
9263 expredir(union node *n)
9264 {
9265         union node *redir;
9266
9267         for (redir = n; redir; redir = redir->nfile.next) {
9268                 struct arglist fn;
9269
9270                 fn.list = NULL;
9271                 fn.lastp = &fn.list;
9272                 switch (redir->type) {
9273                 case NFROMTO:
9274                 case NFROM:
9275                 case NTO:
9276 #if BASH_REDIR_OUTPUT
9277                 case NTO2:
9278 #endif
9279                 case NCLOBBER:
9280                 case NAPPEND:
9281                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9282                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9283 #if BASH_REDIR_OUTPUT
9284  store_expfname:
9285 #endif
9286 #if 0
9287 // By the design of stack allocator, the loop of this kind:
9288 //      while true; do while true; do break; done </dev/null; done
9289 // will look like a memory leak: ash plans to free expfname's
9290 // of "/dev/null" as soon as it finishes running the loop
9291 // (in this case, never).
9292 // This "fix" is wrong:
9293                         if (redir->nfile.expfname)
9294                                 stunalloc(redir->nfile.expfname);
9295 // It results in corrupted state of stacked allocations.
9296 #endif
9297                         redir->nfile.expfname = fn.list->text;
9298                         break;
9299                 case NFROMFD:
9300                 case NTOFD: /* >& */
9301                         if (redir->ndup.vname) {
9302                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9303                                 if (fn.list == NULL)
9304                                         ash_msg_and_raise_error("redir error");
9305 #if BASH_REDIR_OUTPUT
9306 //FIXME: we used expandarg with different args!
9307                                 if (!isdigit_str9(fn.list->text)) {
9308                                         /* >&file, not >&fd */
9309                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9310                                                 ash_msg_and_raise_error("redir error");
9311                                         redir->type = NTO2;
9312                                         goto store_expfname;
9313                                 }
9314 #endif
9315                                 fixredir(redir, fn.list->text, 1);
9316                         }
9317                         break;
9318                 }
9319         }
9320 }
9321
9322 /*
9323  * Evaluate a pipeline.  All the processes in the pipeline are children
9324  * of the process creating the pipeline.  (This differs from some versions
9325  * of the shell, which make the last process in a pipeline the parent
9326  * of all the rest.)
9327  */
9328 static int
9329 evalpipe(union node *n, int flags)
9330 {
9331         struct job *jp;
9332         struct nodelist *lp;
9333         int pipelen;
9334         int prevfd;
9335         int pip[2];
9336         int status = 0;
9337
9338         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9339         pipelen = 0;
9340         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9341                 pipelen++;
9342         flags |= EV_EXIT;
9343         INT_OFF;
9344         if (n->npipe.pipe_backgnd == 0)
9345                 get_tty_state();
9346         jp = makejob(/*n,*/ pipelen);
9347         prevfd = -1;
9348         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9349                 prehash(lp->n);
9350                 pip[1] = -1;
9351                 if (lp->next) {
9352                         if (pipe(pip) < 0) {
9353                                 close(prevfd);
9354                                 ash_msg_and_raise_perror("can't create pipe");
9355                         }
9356                 }
9357                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9358                         /* child */
9359                         INT_ON;
9360                         if (pip[1] >= 0) {
9361                                 close(pip[0]);
9362                         }
9363                         if (prevfd > 0) {
9364                                 dup2(prevfd, 0);
9365                                 close(prevfd);
9366                         }
9367                         if (pip[1] > 1) {
9368                                 dup2(pip[1], 1);
9369                                 close(pip[1]);
9370                         }
9371                         evaltreenr(lp->n, flags);
9372                         /* never returns */
9373                 }
9374                 /* parent */
9375                 if (prevfd >= 0)
9376                         close(prevfd);
9377                 prevfd = pip[0];
9378                 /* Don't want to trigger debugging */
9379                 if (pip[1] != -1)
9380                         close(pip[1]);
9381         }
9382         if (n->npipe.pipe_backgnd == 0) {
9383                 status = waitforjob(jp);
9384                 TRACE(("evalpipe:  job done exit status %d\n", status));
9385         }
9386         INT_ON;
9387
9388         return status;
9389 }
9390
9391 /*
9392  * Controls whether the shell is interactive or not.
9393  */
9394 static void
9395 setinteractive(int on)
9396 {
9397         static smallint is_interactive;
9398
9399         if (++on == is_interactive)
9400                 return;
9401         is_interactive = on;
9402         setsignal(SIGINT);
9403         setsignal(SIGQUIT);
9404         setsignal(SIGTERM);
9405 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9406         if (is_interactive > 1) {
9407                 /* Looks like they want an interactive shell */
9408                 static smallint did_banner;
9409
9410                 if (!did_banner) {
9411                         /* note: ash and hush share this string */
9412                         out1fmt("\n\n%s %s\n"
9413                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9414                                 "\n",
9415                                 bb_banner,
9416                                 "built-in shell (ash)"
9417                         );
9418                         did_banner = 1;
9419                 }
9420         }
9421 #endif
9422 }
9423
9424 static void
9425 optschanged(void)
9426 {
9427 #if DEBUG
9428         opentrace();
9429 #endif
9430         setinteractive(iflag);
9431         setjobctl(mflag);
9432 #if ENABLE_FEATURE_EDITING_VI
9433         if (viflag)
9434                 line_input_state->flags |= VI_MODE;
9435         else
9436                 line_input_state->flags &= ~VI_MODE;
9437 #else
9438         viflag = 0; /* forcibly keep the option off */
9439 #endif
9440 }
9441
9442 struct localvar_list {
9443         struct localvar_list *next;
9444         struct localvar *lv;
9445 };
9446
9447 static struct localvar_list *localvar_stack;
9448
9449 /*
9450  * Called after a function returns.
9451  * Interrupts must be off.
9452  */
9453 static void
9454 poplocalvars(int keep)
9455 {
9456         struct localvar_list *ll;
9457         struct localvar *lvp, *next;
9458         struct var *vp;
9459
9460         INT_OFF;
9461         ll = localvar_stack;
9462         localvar_stack = ll->next;
9463
9464         next = ll->lv;
9465         free(ll);
9466
9467         while ((lvp = next) != NULL) {
9468                 next = lvp->next;
9469                 vp = lvp->vp;
9470                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9471                 if (keep) {
9472                         int bits = VSTRFIXED;
9473
9474                         if (lvp->flags != VUNSET) {
9475                                 if (vp->var_text == lvp->text)
9476                                         bits |= VTEXTFIXED;
9477                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9478                                         free((char*)lvp->text);
9479                         }
9480
9481                         vp->flags &= ~bits;
9482                         vp->flags |= (lvp->flags & bits);
9483
9484                         if ((vp->flags &
9485                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9486                                 unsetvar(vp->var_text);
9487                 } else if (vp == NULL) {        /* $- saved */
9488                         memcpy(optlist, lvp->text, sizeof(optlist));
9489                         free((char*)lvp->text);
9490                         optschanged();
9491                 } else if (lvp->flags == VUNSET) {
9492                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9493                         unsetvar(vp->var_text);
9494                 } else {
9495                         if (vp->var_func)
9496                                 vp->var_func(var_end(lvp->text));
9497                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9498                                 free((char*)vp->var_text);
9499                         vp->flags = lvp->flags;
9500                         vp->var_text = lvp->text;
9501                 }
9502                 free(lvp);
9503         }
9504         INT_ON;
9505 }
9506
9507 /*
9508  * Create a new localvar environment.
9509  */
9510 static struct localvar_list *
9511 pushlocalvars(void)
9512 {
9513         struct localvar_list *ll;
9514
9515         INT_OFF;
9516         ll = ckzalloc(sizeof(*ll));
9517         /*ll->lv = NULL; - zalloc did it */
9518         ll->next = localvar_stack;
9519         localvar_stack = ll;
9520         INT_ON;
9521
9522         return ll->next;
9523 }
9524
9525 static void
9526 unwindlocalvars(struct localvar_list *stop)
9527 {
9528         while (localvar_stack != stop)
9529                 poplocalvars(0);
9530 }
9531
9532 static int
9533 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9534 {
9535         volatile struct shparam saveparam;
9536         struct jmploc *volatile savehandler;
9537         struct jmploc jmploc;
9538         int e;
9539         int savefuncline;
9540
9541         saveparam = shellparam;
9542         savefuncline = funcline;
9543         savehandler = exception_handler;
9544         e = setjmp(jmploc.loc);
9545         if (e) {
9546                 goto funcdone;
9547         }
9548         INT_OFF;
9549         exception_handler = &jmploc;
9550         shellparam.malloced = 0;
9551         func->count++;
9552         funcline = func->n.ndefun.linno;
9553         INT_ON;
9554         shellparam.nparam = argc - 1;
9555         shellparam.p = argv + 1;
9556 #if ENABLE_ASH_GETOPTS
9557         shellparam.optind = 1;
9558         shellparam.optoff = -1;
9559 #endif
9560         pushlocalvars();
9561         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9562         poplocalvars(0);
9563  funcdone:
9564         INT_OFF;
9565         funcline = savefuncline;
9566         freefunc(func);
9567         freeparam(&shellparam);
9568         shellparam = saveparam;
9569         exception_handler = savehandler;
9570         INT_ON;
9571         evalskip &= ~SKIPFUNC;
9572         return e;
9573 }
9574
9575 /*
9576  * Make a variable a local variable.  When a variable is made local, it's
9577  * value and flags are saved in a localvar structure.  The saved values
9578  * will be restored when the shell function returns.  We handle the name
9579  * "-" as a special case: it makes changes to "set +-options" local
9580  * (options will be restored on return from the function).
9581  */
9582 static void
9583 mklocal(char *name)
9584 {
9585         struct localvar *lvp;
9586         struct var **vpp;
9587         struct var *vp;
9588         char *eq = strchr(name, '=');
9589
9590         INT_OFF;
9591         /* Cater for duplicate "local". Examples:
9592          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9593          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9594          */
9595         lvp = localvar_stack->lv;
9596         while (lvp) {
9597                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9598                         if (eq)
9599                                 setvareq(name, 0);
9600                         /* else:
9601                          * it's a duplicate "local VAR" declaration, do nothing
9602                          */
9603                         goto ret;
9604                 }
9605                 lvp = lvp->next;
9606         }
9607
9608         lvp = ckzalloc(sizeof(*lvp));
9609         if (LONE_DASH(name)) {
9610                 char *p;
9611                 p = ckmalloc(sizeof(optlist));
9612                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9613                 vp = NULL;
9614         } else {
9615                 vpp = hashvar(name);
9616                 vp = *findvar(vpp, name);
9617                 if (vp == NULL) {
9618                         /* variable did not exist yet */
9619                         if (eq)
9620                                 vp = setvareq(name, VSTRFIXED);
9621                         else
9622                                 vp = setvar(name, NULL, VSTRFIXED);
9623                         lvp->flags = VUNSET;
9624                 } else {
9625                         lvp->text = vp->var_text;
9626                         lvp->flags = vp->flags;
9627                         /* make sure neither "struct var" nor string gets freed
9628                          * during (un)setting:
9629                          */
9630                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9631                         if (eq)
9632                                 setvareq(name, 0);
9633                         else
9634                                 /* "local VAR" unsets VAR: */
9635                                 setvar0(name, NULL);
9636                 }
9637         }
9638         lvp->vp = vp;
9639         lvp->next = localvar_stack->lv;
9640         localvar_stack->lv = lvp;
9641  ret:
9642         INT_ON;
9643 }
9644
9645 /*
9646  * The "local" command.
9647  */
9648 static int FAST_FUNC
9649 localcmd(int argc UNUSED_PARAM, char **argv)
9650 {
9651         char *name;
9652
9653         if (!localvar_stack)
9654                 ash_msg_and_raise_error("not in a function");
9655
9656         argv = argptr;
9657         while ((name = *argv++) != NULL) {
9658                 mklocal(name);
9659         }
9660         return 0;
9661 }
9662
9663 static int FAST_FUNC
9664 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9665 {
9666         return 1;
9667 }
9668
9669 static int FAST_FUNC
9670 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9671 {
9672         return 0;
9673 }
9674
9675 static int FAST_FUNC
9676 execcmd(int argc UNUSED_PARAM, char **argv)
9677 {
9678         optionarg = NULL;
9679         while (nextopt("a:") != '\0')
9680                 /* nextopt() sets optionarg to "-a ARGV0" */;
9681
9682         argv = argptr;
9683         if (argv[0]) {
9684                 char *prog;
9685
9686                 iflag = 0;              /* exit on error */
9687                 mflag = 0;
9688                 optschanged();
9689                 /* We should set up signals for "exec CMD"
9690                  * the same way as for "CMD" without "exec".
9691                  * But optschanged->setinteractive->setsignal
9692                  * still thought we are a root shell. Therefore, for example,
9693                  * SIGQUIT is still set to IGN. Fix it:
9694                  */
9695                 shlvl++;
9696                 setsignal(SIGQUIT);
9697                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9698                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9699                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9700
9701                 prog = argv[0];
9702                 if (optionarg)
9703                         argv[0] = optionarg;
9704                 shellexec(prog, argv, pathval(), 0);
9705                 /* NOTREACHED */
9706         }
9707         return 0;
9708 }
9709
9710 /*
9711  * The return command.
9712  */
9713 static int FAST_FUNC
9714 returncmd(int argc UNUSED_PARAM, char **argv)
9715 {
9716         /*
9717          * If called outside a function, do what ksh does;
9718          * skip the rest of the file.
9719          */
9720         evalskip = SKIPFUNC;
9721         return argv[1] ? number(argv[1]) : exitstatus;
9722 }
9723
9724 /* Forward declarations for builtintab[] */
9725 static int breakcmd(int, char **) FAST_FUNC;
9726 static int dotcmd(int, char **) FAST_FUNC;
9727 static int evalcmd(int, char **, int) FAST_FUNC;
9728 static int exitcmd(int, char **) FAST_FUNC;
9729 static int exportcmd(int, char **) FAST_FUNC;
9730 #if ENABLE_ASH_GETOPTS
9731 static int getoptscmd(int, char **) FAST_FUNC;
9732 #endif
9733 #if ENABLE_ASH_HELP
9734 static int helpcmd(int, char **) FAST_FUNC;
9735 #endif
9736 #if MAX_HISTORY
9737 static int historycmd(int, char **) FAST_FUNC;
9738 #endif
9739 #if ENABLE_FEATURE_SH_MATH
9740 static int letcmd(int, char **) FAST_FUNC;
9741 #endif
9742 static int readcmd(int, char **) FAST_FUNC;
9743 static int setcmd(int, char **) FAST_FUNC;
9744 static int shiftcmd(int, char **) FAST_FUNC;
9745 static int timescmd(int, char **) FAST_FUNC;
9746 static int trapcmd(int, char **) FAST_FUNC;
9747 static int umaskcmd(int, char **) FAST_FUNC;
9748 static int unsetcmd(int, char **) FAST_FUNC;
9749 static int ulimitcmd(int, char **) FAST_FUNC;
9750
9751 #define BUILTIN_NOSPEC          "0"
9752 #define BUILTIN_SPECIAL         "1"
9753 #define BUILTIN_REGULAR         "2"
9754 #define BUILTIN_SPEC_REG        "3"
9755 #define BUILTIN_ASSIGN          "4"
9756 #define BUILTIN_SPEC_ASSG       "5"
9757 #define BUILTIN_REG_ASSG        "6"
9758 #define BUILTIN_SPEC_REG_ASSG   "7"
9759
9760 /* Stubs for calling non-FAST_FUNC's */
9761 #if ENABLE_ASH_ECHO
9762 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9763 #endif
9764 #if ENABLE_ASH_PRINTF
9765 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9766 #endif
9767 #if ENABLE_ASH_TEST || BASH_TEST2
9768 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9769 #endif
9770
9771 /* Keep these in proper order since it is searched via bsearch() */
9772 static const struct builtincmd builtintab[] = {
9773         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9774         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9775 #if ENABLE_ASH_TEST
9776         { BUILTIN_REGULAR       "["       , testcmd    },
9777 #endif
9778 #if BASH_TEST2
9779         { BUILTIN_REGULAR       "[["      , testcmd    },
9780 #endif
9781 #if ENABLE_ASH_ALIAS
9782         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9783 #endif
9784 #if JOBS
9785         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9786 #endif
9787         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9788         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9789         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9790 #if ENABLE_ASH_CMDCMD
9791         { BUILTIN_REGULAR       "command" , commandcmd },
9792 #endif
9793         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9794 #if ENABLE_ASH_ECHO
9795         { BUILTIN_REGULAR       "echo"    , echocmd    },
9796 #endif
9797         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9798         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9799         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9800         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9801         { BUILTIN_REGULAR       "false"   , falsecmd   },
9802 #if JOBS
9803         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9804 #endif
9805 #if ENABLE_ASH_GETOPTS
9806         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9807 #endif
9808         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9809 #if ENABLE_ASH_HELP
9810         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9811 #endif
9812 #if MAX_HISTORY
9813         { BUILTIN_NOSPEC        "history" , historycmd },
9814 #endif
9815 #if JOBS
9816         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9817         { BUILTIN_REGULAR       "kill"    , killcmd    },
9818 #endif
9819 #if ENABLE_FEATURE_SH_MATH
9820         { BUILTIN_NOSPEC        "let"     , letcmd     },
9821 #endif
9822         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9823 #if ENABLE_ASH_PRINTF
9824         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9825 #endif
9826         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9827         { BUILTIN_REGULAR       "read"    , readcmd    },
9828         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9829         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9830         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9831         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9832 #if BASH_SOURCE
9833         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9834 #endif
9835 #if ENABLE_ASH_TEST
9836         { BUILTIN_REGULAR       "test"    , testcmd    },
9837 #endif
9838         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9839         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9840         { BUILTIN_REGULAR       "true"    , truecmd    },
9841         { BUILTIN_NOSPEC        "type"    , typecmd    },
9842         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9843         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9844 #if ENABLE_ASH_ALIAS
9845         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9846 #endif
9847         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9848         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9849 };
9850
9851 /* Should match the above table! */
9852 #define COMMANDCMD (builtintab + \
9853         /* . : */       2 + \
9854         /* [ */         1 * ENABLE_ASH_TEST + \
9855         /* [[ */        1 * BASH_TEST2 + \
9856         /* alias */     1 * ENABLE_ASH_ALIAS + \
9857         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9858         /* break cd cddir  */   3)
9859 #define EVALCMD (COMMANDCMD + \
9860         /* command */   1 * ENABLE_ASH_CMDCMD + \
9861         /* continue */  1 + \
9862         /* echo */      1 * ENABLE_ASH_ECHO + \
9863         0)
9864 #define EXECCMD (EVALCMD + \
9865         /* eval */      1)
9866
9867 /*
9868  * Search the table of builtin commands.
9869  */
9870 static int
9871 pstrcmp1(const void *a, const void *b)
9872 {
9873         return strcmp((char*)a, *(char**)b + 1);
9874 }
9875 static struct builtincmd *
9876 find_builtin(const char *name)
9877 {
9878         struct builtincmd *bp;
9879
9880         bp = bsearch(
9881                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9882                 pstrcmp1
9883         );
9884         return bp;
9885 }
9886
9887 /*
9888  * Execute a simple command.
9889  */
9890 static int
9891 isassignment(const char *p)
9892 {
9893         const char *q = endofname(p);
9894         if (p == q)
9895                 return 0;
9896         return *q == '=';
9897 }
9898 static int FAST_FUNC
9899 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9900 {
9901         /* Preserve exitstatus of a previous possible redirection
9902          * as POSIX mandates */
9903         return back_exitstatus;
9904 }
9905 static int
9906 evalcommand(union node *cmd, int flags)
9907 {
9908         static const struct builtincmd null_bltin = {
9909                 "\0\0", bltincmd /* why three NULs? */
9910         };
9911         struct localvar_list *localvar_stop;
9912         struct redirtab *redir_stop;
9913         struct stackmark smark;
9914         union node *argp;
9915         struct arglist arglist;
9916         struct arglist varlist;
9917         char **argv;
9918         int argc;
9919         const struct strlist *sp;
9920         struct cmdentry cmdentry;
9921         struct job *jp;
9922         char *lastarg;
9923         const char *path;
9924         int spclbltin;
9925         int status;
9926         char **nargv;
9927         smallint cmd_is_exec;
9928
9929         errlinno = lineno = cmd->ncmd.linno;
9930         if (funcline)
9931                 lineno -= funcline - 1;
9932
9933         /* First expand the arguments. */
9934         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9935         setstackmark(&smark);
9936         localvar_stop = pushlocalvars();
9937         back_exitstatus = 0;
9938
9939         cmdentry.cmdtype = CMDBUILTIN;
9940         cmdentry.u.cmd = &null_bltin;
9941         varlist.lastp = &varlist.list;
9942         *varlist.lastp = NULL;
9943         arglist.lastp = &arglist.list;
9944         *arglist.lastp = NULL;
9945
9946         argc = 0;
9947         if (cmd->ncmd.args) {
9948                 struct builtincmd *bcmd;
9949                 smallint pseudovarflag;
9950
9951                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9952                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9953
9954                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9955                         struct strlist **spp;
9956
9957                         spp = arglist.lastp;
9958                         if (pseudovarflag && isassignment(argp->narg.text))
9959                                 expandarg(argp, &arglist, EXP_VARTILDE);
9960                         else
9961                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9962
9963                         for (sp = *spp; sp; sp = sp->next)
9964                                 argc++;
9965                 }
9966         }
9967
9968         /* Reserve one extra spot at the front for shellexec. */
9969         nargv = stalloc(sizeof(char *) * (argc + 2));
9970         argv = ++nargv;
9971         for (sp = arglist.list; sp; sp = sp->next) {
9972                 TRACE(("evalcommand arg: %s\n", sp->text));
9973                 *nargv++ = sp->text;
9974         }
9975         *nargv = NULL;
9976
9977         lastarg = NULL;
9978         if (iflag && funcline == 0 && argc > 0)
9979                 lastarg = nargv[-1];
9980
9981         expredir(cmd->ncmd.redirect);
9982         redir_stop = pushredir(cmd->ncmd.redirect);
9983         preverrout_fd = 2;
9984         if (BASH_XTRACEFD && xflag) {
9985                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9986                  * we do not emulate this. We only use its value.
9987                  */
9988                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9989                 if (xtracefd && is_number(xtracefd))
9990                         preverrout_fd = atoi(xtracefd);
9991
9992         }
9993         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9994
9995         path = vpath.var_text;
9996         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9997                 struct strlist **spp;
9998                 char *p;
9999
10000                 spp = varlist.lastp;
10001                 expandarg(argp, &varlist, EXP_VARTILDE);
10002
10003                 mklocal((*spp)->text);
10004
10005                 /*
10006                  * Modify the command lookup path, if a PATH= assignment
10007                  * is present
10008                  */
10009                 p = (*spp)->text;
10010                 if (varcmp(p, path) == 0)
10011                         path = p;
10012         }
10013
10014         /* Print the command if xflag is set. */
10015         if (xflag) {
10016                 const char *pfx = "";
10017
10018                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10019
10020                 sp = varlist.list;
10021                 while (sp) {
10022                         char *varval = sp->text;
10023                         char *eq = strchrnul(varval, '=');
10024                         if (*eq)
10025                                 eq++;
10026                         fdprintf(preverrout_fd, "%s%.*s%s",
10027                                 pfx,
10028                                 (int)(eq - varval), varval,
10029                                 maybe_single_quote(eq)
10030                         );
10031                         sp = sp->next;
10032                         pfx = " ";
10033                 }
10034
10035                 sp = arglist.list;
10036                 while (sp) {
10037                         fdprintf(preverrout_fd, "%s%s",
10038                                 pfx,
10039                                 /* always quote if matches reserved word: */
10040                                 findkwd(sp->text)
10041                                 ? single_quote(sp->text)
10042                                 : maybe_single_quote(sp->text)
10043                         );
10044                         sp = sp->next;
10045                         pfx = " ";
10046                 }
10047                 safe_write(preverrout_fd, "\n", 1);
10048         }
10049
10050         cmd_is_exec = 0;
10051         spclbltin = -1;
10052
10053         /* Now locate the command. */
10054         if (argc) {
10055                 int cmd_flag = DO_ERR;
10056 #if ENABLE_ASH_CMDCMD
10057                 const char *oldpath = path + 5;
10058 #endif
10059                 path += 5;
10060                 for (;;) {
10061                         find_command(argv[0], &cmdentry, cmd_flag, path);
10062                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10063                                 flush_stdout_stderr();
10064                                 status = 127;
10065                                 goto bail;
10066                         }
10067
10068                         /* implement bltin and command here */
10069                         if (cmdentry.cmdtype != CMDBUILTIN)
10070                                 break;
10071                         if (spclbltin < 0)
10072                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10073                         if (cmdentry.u.cmd == EXECCMD)
10074                                 cmd_is_exec = 1;
10075 #if ENABLE_ASH_CMDCMD
10076                         if (cmdentry.u.cmd == COMMANDCMD) {
10077                                 path = oldpath;
10078                                 nargv = parse_command_args(argv, &path);
10079                                 if (!nargv)
10080                                         break;
10081                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10082                                  * nargv => "PROG". path is updated if -p.
10083                                  */
10084                                 argc -= nargv - argv;
10085                                 argv = nargv;
10086                                 cmd_flag |= DO_NOFUNC;
10087                         } else
10088 #endif
10089                                 break;
10090                 }
10091         }
10092
10093         if (status) {
10094  bail:
10095                 exitstatus = status;
10096
10097                 /* We have a redirection error. */
10098                 if (spclbltin > 0)
10099                         raise_exception(EXERROR);
10100
10101                 goto out;
10102         }
10103
10104         /* Execute the command. */
10105         switch (cmdentry.cmdtype) {
10106         default: {
10107
10108 #if ENABLE_FEATURE_SH_STANDALONE \
10109  && ENABLE_FEATURE_SH_NOFORK \
10110  && NUM_APPLETS > 1
10111 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10112  *     around run_nofork_applet() call.
10113  * (2) Should this check also be done in forkshell()?
10114  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10115  */
10116                 /* find_command() encodes applet_no as (-2 - applet_no) */
10117                 int applet_no = (- cmdentry.u.index - 2);
10118                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10119                         char **sv_environ;
10120
10121                         INT_OFF;
10122                         sv_environ = environ;
10123                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10124                         /*
10125                          * Run <applet>_main().
10126                          * Signals (^C) can't interrupt here.
10127                          * Otherwise we can mangle stdio or malloc internal state.
10128                          * This makes applets which can run for a long time
10129                          * and/or wait for user input ineligible for NOFORK:
10130                          * for example, "yes" or "rm" (rm -i waits for input).
10131                          */
10132                         status = run_nofork_applet(applet_no, argv);
10133                         environ = sv_environ;
10134                         /*
10135                          * Try enabling NOFORK for "yes" applet.
10136                          * ^C _will_ stop it (write returns EINTR),
10137                          * but this causes stdout FILE to be stuck
10138                          * and needing clearerr(). What if other applets
10139                          * also can get EINTRs? Do we need to switch
10140                          * our signals to SA_RESTART?
10141                          */
10142                         /*clearerr(stdout);*/
10143                         INT_ON;
10144                         break;
10145                 }
10146 #endif
10147                 /* Can we avoid forking? For example, very last command
10148                  * in a script or a subshell does not need forking,
10149                  * we can just exec it.
10150                  */
10151                 if (!(flags & EV_EXIT) || may_have_traps) {
10152                         /* No, forking off a child is necessary */
10153                         INT_OFF;
10154                         get_tty_state();
10155                         jp = makejob(/*cmd,*/ 1);
10156                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10157                                 /* parent */
10158                                 status = waitforjob(jp);
10159                                 INT_ON;
10160                                 TRACE(("forked child exited with %d\n", status));
10161                                 break;
10162                         }
10163                         /* child */
10164                         FORCE_INT_ON;
10165                         /* fall through to exec'ing external program */
10166                 }
10167                 listsetvar(varlist.list, VEXPORT|VSTACK);
10168                 shellexec(argv[0], argv, path, cmdentry.u.index);
10169                 /* NOTREACHED */
10170         } /* default */
10171         case CMDBUILTIN:
10172                 if (spclbltin > 0 || argc == 0) {
10173                         poplocalvars(1);
10174                         if (cmd_is_exec && argc > 1)
10175                                 listsetvar(varlist.list, VEXPORT);
10176                 }
10177
10178                 /* Tight loop with builtins only:
10179                  * "while kill -0 $child; do true; done"
10180                  * will never exit even if $child died, unless we do this
10181                  * to reap the zombie and make kill detect that it's gone: */
10182                 dowait(DOWAIT_NONBLOCK, NULL);
10183
10184                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10185                         if (exception_type == EXERROR && spclbltin <= 0) {
10186                                 FORCE_INT_ON;
10187                                 goto readstatus;
10188                         }
10189  raise:
10190                         longjmp(exception_handler->loc, 1);
10191                 }
10192                 goto readstatus;
10193
10194         case CMDFUNCTION:
10195                 poplocalvars(1);
10196                 /* See above for the rationale */
10197                 dowait(DOWAIT_NONBLOCK, NULL);
10198                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10199                         goto raise;
10200  readstatus:
10201                 status = exitstatus;
10202                 break;
10203         } /* switch */
10204
10205  out:
10206         if (cmd->ncmd.redirect)
10207                 popredir(/*drop:*/ cmd_is_exec);
10208         unwindredir(redir_stop);
10209         unwindlocalvars(localvar_stop);
10210         if (lastarg) {
10211                 /* dsl: I think this is intended to be used to support
10212                  * '_' in 'vi' command mode during line editing...
10213                  * However I implemented that within libedit itself.
10214                  */
10215                 setvar0("_", lastarg);
10216         }
10217         popstackmark(&smark);
10218
10219         return status;
10220 }
10221
10222 static int
10223 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10224 {
10225         char *volatile savecmdname;
10226         struct jmploc *volatile savehandler;
10227         struct jmploc jmploc;
10228         int status;
10229         int i;
10230
10231         savecmdname = commandname;
10232         savehandler = exception_handler;
10233         i = setjmp(jmploc.loc);
10234         if (i)
10235                 goto cmddone;
10236         exception_handler = &jmploc;
10237         commandname = argv[0];
10238         argptr = argv + 1;
10239         optptr = NULL;                  /* initialize nextopt */
10240         if (cmd == EVALCMD)
10241                 status = evalcmd(argc, argv, flags);
10242         else
10243                 status = (*cmd->builtin)(argc, argv);
10244         flush_stdout_stderr();
10245         status |= ferror(stdout);
10246         exitstatus = status;
10247  cmddone:
10248         clearerr(stdout);
10249         commandname = savecmdname;
10250         exception_handler = savehandler;
10251
10252         return i;
10253 }
10254
10255 static int
10256 goodname(const char *p)
10257 {
10258         return endofname(p)[0] == '\0';
10259 }
10260
10261
10262 /*
10263  * Search for a command.  This is called before we fork so that the
10264  * location of the command will be available in the parent as well as
10265  * the child.  The check for "goodname" is an overly conservative
10266  * check that the name will not be subject to expansion.
10267  */
10268 static void
10269 prehash(union node *n)
10270 {
10271         struct cmdentry entry;
10272
10273         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10274                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10275 }
10276
10277
10278 /* ============ Builtin commands
10279  *
10280  * Builtin commands whose functions are closely tied to evaluation
10281  * are implemented here.
10282  */
10283
10284 /*
10285  * Handle break and continue commands.  Break, continue, and return are
10286  * all handled by setting the evalskip flag.  The evaluation routines
10287  * above all check this flag, and if it is set they start skipping
10288  * commands rather than executing them.  The variable skipcount is
10289  * the number of loops to break/continue, or the number of function
10290  * levels to return.  (The latter is always 1.)  It should probably
10291  * be an error to break out of more loops than exist, but it isn't
10292  * in the standard shell so we don't make it one here.
10293  */
10294 static int FAST_FUNC
10295 breakcmd(int argc UNUSED_PARAM, char **argv)
10296 {
10297         int n = argv[1] ? number(argv[1]) : 1;
10298
10299         if (n <= 0)
10300                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10301         if (n > loopnest)
10302                 n = loopnest;
10303         if (n > 0) {
10304                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10305                 skipcount = n;
10306         }
10307         return 0;
10308 }
10309
10310
10311 /*
10312  * This implements the input routines used by the parser.
10313  */
10314
10315 enum {
10316         INPUT_PUSH_FILE = 1,
10317         INPUT_NOFILE_OK = 2,
10318 };
10319
10320 static smallint checkkwd;
10321 /* values of checkkwd variable */
10322 #define CHKALIAS        0x1
10323 #define CHKKWD          0x2
10324 #define CHKNL           0x4
10325 #define CHKEOFMARK      0x8
10326
10327 /*
10328  * Push a string back onto the input at this current parsefile level.
10329  * We handle aliases this way.
10330  */
10331 #if !ENABLE_ASH_ALIAS
10332 #define pushstring(s, ap) pushstring(s)
10333 #endif
10334 static void
10335 pushstring(char *s, struct alias *ap)
10336 {
10337         struct strpush *sp;
10338         int len;
10339
10340         len = strlen(s);
10341         INT_OFF;
10342         if (g_parsefile->strpush) {
10343                 sp = ckzalloc(sizeof(*sp));
10344                 sp->prev = g_parsefile->strpush;
10345         } else {
10346                 sp = &(g_parsefile->basestrpush);
10347         }
10348         g_parsefile->strpush = sp;
10349         sp->prev_string = g_parsefile->next_to_pgetc;
10350         sp->prev_left_in_line = g_parsefile->left_in_line;
10351         sp->unget = g_parsefile->unget;
10352         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10353 #if ENABLE_ASH_ALIAS
10354         sp->ap = ap;
10355         if (ap) {
10356                 ap->flag |= ALIASINUSE;
10357                 sp->string = s;
10358         }
10359 #endif
10360         g_parsefile->next_to_pgetc = s;
10361         g_parsefile->left_in_line = len;
10362         g_parsefile->unget = 0;
10363         INT_ON;
10364 }
10365
10366 static void
10367 popstring(void)
10368 {
10369         struct strpush *sp = g_parsefile->strpush;
10370
10371         INT_OFF;
10372 #if ENABLE_ASH_ALIAS
10373         if (sp->ap) {
10374                 if (g_parsefile->next_to_pgetc[-1] == ' '
10375                  || g_parsefile->next_to_pgetc[-1] == '\t'
10376                 ) {
10377                         checkkwd |= CHKALIAS;
10378                 }
10379                 if (sp->string != sp->ap->val) {
10380                         free(sp->string);
10381                 }
10382                 sp->ap->flag &= ~ALIASINUSE;
10383                 if (sp->ap->flag & ALIASDEAD) {
10384                         unalias(sp->ap->name);
10385                 }
10386         }
10387 #endif
10388         g_parsefile->next_to_pgetc = sp->prev_string;
10389         g_parsefile->left_in_line = sp->prev_left_in_line;
10390         g_parsefile->unget = sp->unget;
10391         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10392         g_parsefile->strpush = sp->prev;
10393         if (sp != &(g_parsefile->basestrpush))
10394                 free(sp);
10395         INT_ON;
10396 }
10397
10398 static int
10399 preadfd(void)
10400 {
10401         int nr;
10402         char *buf = g_parsefile->buf;
10403
10404         g_parsefile->next_to_pgetc = buf;
10405 #if ENABLE_FEATURE_EDITING
10406  retry:
10407         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10408                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10409         else {
10410 # if ENABLE_ASH_IDLE_TIMEOUT
10411                 int timeout = -1;
10412                 if (iflag) {
10413                         const char *tmout_var = lookupvar("TMOUT");
10414                         if (tmout_var) {
10415                                 timeout = atoi(tmout_var) * 1000;
10416                                 if (timeout <= 0)
10417                                         timeout = -1;
10418                         }
10419                 }
10420                 line_input_state->timeout = timeout;
10421 # endif
10422 # if ENABLE_FEATURE_TAB_COMPLETION
10423                 line_input_state->path_lookup = pathval();
10424 # endif
10425                 reinit_unicode_for_ash();
10426                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10427                 if (nr == 0) {
10428                         /* ^C pressed, "convert" to SIGINT */
10429                         write(STDOUT_FILENO, "^C", 2);
10430                         if (trap[SIGINT]) {
10431                                 buf[0] = '\n';
10432                                 buf[1] = '\0';
10433                                 raise(SIGINT);
10434                                 return 1;
10435                         }
10436                         exitstatus = 128 + SIGINT;
10437                         bb_putchar('\n');
10438                         goto retry;
10439                 }
10440                 if (nr < 0) {
10441                         if (errno == 0) {
10442                                 /* Ctrl+D pressed */
10443                                 nr = 0;
10444                         }
10445 # if ENABLE_ASH_IDLE_TIMEOUT
10446                         else if (errno == EAGAIN && timeout > 0) {
10447                                 puts("\007timed out waiting for input: auto-logout");
10448                                 exitshell();
10449                         }
10450 # endif
10451                 }
10452         }
10453 #else
10454         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10455 #endif
10456
10457 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10458         if (nr < 0) {
10459                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10460                         int flags = fcntl(0, F_GETFL);
10461                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10462                                 flags &= ~O_NONBLOCK;
10463                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10464                                         out2str("sh: turning off NDELAY mode\n");
10465                                         goto retry;
10466                                 }
10467                         }
10468                 }
10469         }
10470 #endif
10471         return nr;
10472 }
10473
10474 /*
10475  * Refill the input buffer and return the next input character:
10476  *
10477  * 1) If a string was pushed back on the input, pop it;
10478  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10479  *    or we are reading from a string so we can't refill the buffer,
10480  *    return EOF.
10481  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10482  * 4) Process input up to the next newline, deleting nul characters.
10483  */
10484 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10485 #define pgetc_debug(...) ((void)0)
10486 static int pgetc(void);
10487 static int
10488 preadbuffer(void)
10489 {
10490         char *q;
10491         int more;
10492
10493         if (g_parsefile->strpush) {
10494 #if ENABLE_ASH_ALIAS
10495                 if (g_parsefile->left_in_line == -1
10496                  && g_parsefile->strpush->ap
10497                  && g_parsefile->next_to_pgetc[-1] != ' '
10498                  && g_parsefile->next_to_pgetc[-1] != '\t'
10499                 ) {
10500                         pgetc_debug("preadbuffer PEOA");
10501                         return PEOA;
10502                 }
10503 #endif
10504                 popstring();
10505                 return pgetc();
10506         }
10507         /* on both branches above g_parsefile->left_in_line < 0.
10508          * "pgetc" needs refilling.
10509          */
10510
10511         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10512          * pungetc() may increment it a few times.
10513          * Assuming it won't increment it to less than -90.
10514          */
10515         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10516                 pgetc_debug("preadbuffer PEOF1");
10517                 /* even in failure keep left_in_line and next_to_pgetc
10518                  * in lock step, for correct multi-layer pungetc.
10519                  * left_in_line was decremented before preadbuffer(),
10520                  * must inc next_to_pgetc: */
10521                 g_parsefile->next_to_pgetc++;
10522                 return PEOF;
10523         }
10524
10525         more = g_parsefile->left_in_buffer;
10526         if (more <= 0) {
10527                 flush_stdout_stderr();
10528  again:
10529                 more = preadfd();
10530                 if (more <= 0) {
10531                         /* don't try reading again */
10532                         g_parsefile->left_in_line = -99;
10533                         pgetc_debug("preadbuffer PEOF2");
10534                         g_parsefile->next_to_pgetc++;
10535                         return PEOF;
10536                 }
10537         }
10538
10539         /* Find out where's the end of line.
10540          * Set g_parsefile->left_in_line
10541          * and g_parsefile->left_in_buffer acordingly.
10542          * NUL chars are deleted.
10543          */
10544         q = g_parsefile->next_to_pgetc;
10545         for (;;) {
10546                 char c;
10547
10548                 more--;
10549
10550                 c = *q;
10551                 if (c == '\0') {
10552                         memmove(q, q + 1, more);
10553                 } else {
10554                         q++;
10555                         if (c == '\n') {
10556                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10557                                 break;
10558                         }
10559                 }
10560
10561                 if (more <= 0) {
10562                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10563                         if (g_parsefile->left_in_line < 0)
10564                                 goto again;
10565                         break;
10566                 }
10567         }
10568         g_parsefile->left_in_buffer = more;
10569
10570         if (vflag) {
10571                 char save = *q;
10572                 *q = '\0';
10573                 out2str(g_parsefile->next_to_pgetc);
10574                 *q = save;
10575         }
10576
10577         pgetc_debug("preadbuffer at %d:%p'%s'",
10578                         g_parsefile->left_in_line,
10579                         g_parsefile->next_to_pgetc,
10580                         g_parsefile->next_to_pgetc);
10581         return (unsigned char)*g_parsefile->next_to_pgetc++;
10582 }
10583
10584 static void
10585 nlprompt(void)
10586 {
10587         g_parsefile->linno++;
10588         setprompt_if(doprompt, 2);
10589 }
10590 static void
10591 nlnoprompt(void)
10592 {
10593         g_parsefile->linno++;
10594         needprompt = doprompt;
10595 }
10596
10597 static int
10598 pgetc(void)
10599 {
10600         int c;
10601
10602         pgetc_debug("pgetc at %d:%p'%s'",
10603                         g_parsefile->left_in_line,
10604                         g_parsefile->next_to_pgetc,
10605                         g_parsefile->next_to_pgetc);
10606         if (g_parsefile->unget)
10607                 return g_parsefile->lastc[--g_parsefile->unget];
10608
10609         if (--g_parsefile->left_in_line >= 0)
10610                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10611         else
10612                 c = preadbuffer();
10613
10614         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10615         g_parsefile->lastc[0] = c;
10616
10617         return c;
10618 }
10619
10620 #if ENABLE_ASH_ALIAS
10621 static int
10622 pgetc_without_PEOA(void)
10623 {
10624         int c;
10625         do {
10626                 pgetc_debug("pgetc at %d:%p'%s'",
10627                                 g_parsefile->left_in_line,
10628                                 g_parsefile->next_to_pgetc,
10629                                 g_parsefile->next_to_pgetc);
10630                 c = pgetc();
10631         } while (c == PEOA);
10632         return c;
10633 }
10634 #else
10635 # define pgetc_without_PEOA() pgetc()
10636 #endif
10637
10638 /*
10639  * Undo a call to pgetc.  Only two characters may be pushed back.
10640  * PEOF may be pushed back.
10641  */
10642 static void
10643 pungetc(void)
10644 {
10645         g_parsefile->unget++;
10646 }
10647
10648 /* This one eats backslash+newline */
10649 static int
10650 pgetc_eatbnl(void)
10651 {
10652         int c;
10653
10654         while ((c = pgetc()) == '\\') {
10655                 if (pgetc() != '\n') {
10656                         pungetc();
10657                         break;
10658                 }
10659
10660                 nlprompt();
10661         }
10662
10663         return c;
10664 }
10665
10666 /*
10667  * To handle the "." command, a stack of input files is used.  Pushfile
10668  * adds a new entry to the stack and popfile restores the previous level.
10669  */
10670 static void
10671 pushfile(void)
10672 {
10673         struct parsefile *pf;
10674
10675         pf = ckzalloc(sizeof(*pf));
10676         pf->prev = g_parsefile;
10677         pf->pf_fd = -1;
10678         /*pf->strpush = NULL; - ckzalloc did it */
10679         /*pf->basestrpush.prev = NULL;*/
10680         /*pf->unget = 0;*/
10681         g_parsefile = pf;
10682 }
10683
10684 static void
10685 popfile(void)
10686 {
10687         struct parsefile *pf = g_parsefile;
10688
10689         if (pf == &basepf)
10690                 return;
10691
10692         INT_OFF;
10693         if (pf->pf_fd >= 0)
10694                 close(pf->pf_fd);
10695         free(pf->buf);
10696         while (pf->strpush)
10697                 popstring();
10698         g_parsefile = pf->prev;
10699         free(pf);
10700         INT_ON;
10701 }
10702
10703 /*
10704  * Return to top level.
10705  */
10706 static void
10707 popallfiles(void)
10708 {
10709         while (g_parsefile != &basepf)
10710                 popfile();
10711 }
10712
10713 /*
10714  * Close the file(s) that the shell is reading commands from.  Called
10715  * after a fork is done.
10716  */
10717 static void
10718 closescript(void)
10719 {
10720         popallfiles();
10721         if (g_parsefile->pf_fd > 0) {
10722                 close(g_parsefile->pf_fd);
10723                 g_parsefile->pf_fd = 0;
10724         }
10725 }
10726
10727 /*
10728  * Like setinputfile, but takes an open file descriptor.  Call this with
10729  * interrupts off.
10730  */
10731 static void
10732 setinputfd(int fd, int push)
10733 {
10734         if (push) {
10735                 pushfile();
10736                 g_parsefile->buf = NULL;
10737         }
10738         g_parsefile->pf_fd = fd;
10739         if (g_parsefile->buf == NULL)
10740                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10741         g_parsefile->left_in_buffer = 0;
10742         g_parsefile->left_in_line = 0;
10743         g_parsefile->linno = 1;
10744 }
10745
10746 /*
10747  * Set the input to take input from a file.  If push is set, push the
10748  * old input onto the stack first.
10749  */
10750 static int
10751 setinputfile(const char *fname, int flags)
10752 {
10753         int fd;
10754
10755         INT_OFF;
10756         fd = open(fname, O_RDONLY);
10757         if (fd < 0) {
10758                 if (flags & INPUT_NOFILE_OK)
10759                         goto out;
10760                 exitstatus = 127;
10761                 ash_msg_and_raise_perror("can't open '%s'", fname);
10762         }
10763         if (fd < 10)
10764                 fd = savefd(fd);
10765         else
10766                 close_on_exec_on(fd);
10767         setinputfd(fd, flags & INPUT_PUSH_FILE);
10768  out:
10769         INT_ON;
10770         return fd;
10771 }
10772
10773 /*
10774  * Like setinputfile, but takes input from a string.
10775  */
10776 static void
10777 setinputstring(char *string)
10778 {
10779         INT_OFF;
10780         pushfile();
10781         g_parsefile->next_to_pgetc = string;
10782         g_parsefile->left_in_line = strlen(string);
10783         g_parsefile->buf = NULL;
10784         g_parsefile->linno = 1;
10785         INT_ON;
10786 }
10787
10788
10789 /*
10790  * Routines to check for mail.
10791  */
10792
10793 #if ENABLE_ASH_MAIL
10794
10795 /* Hash of mtimes of mailboxes */
10796 static unsigned mailtime_hash;
10797 /* Set if MAIL or MAILPATH is changed. */
10798 static smallint mail_var_path_changed;
10799
10800 /*
10801  * Print appropriate message(s) if mail has arrived.
10802  * If mail_var_path_changed is set,
10803  * then the value of MAIL has mail_var_path_changed,
10804  * so we just update the values.
10805  */
10806 static void
10807 chkmail(void)
10808 {
10809         const char *mpath;
10810         char *p;
10811         char *q;
10812         unsigned new_hash;
10813         struct stackmark smark;
10814         struct stat statb;
10815
10816         setstackmark(&smark);
10817         mpath = mpathset() ? mpathval() : mailval();
10818         new_hash = 0;
10819         for (;;) {
10820                 p = path_advance(&mpath, nullstr);
10821                 if (p == NULL)
10822                         break;
10823                 if (*p == '\0')
10824                         continue;
10825                 for (q = p; *q; q++)
10826                         continue;
10827 #if DEBUG
10828                 if (q[-1] != '/')
10829                         abort();
10830 #endif
10831                 q[-1] = '\0';                   /* delete trailing '/' */
10832                 if (stat(p, &statb) < 0) {
10833                         continue;
10834                 }
10835                 /* Very simplistic "hash": just a sum of all mtimes */
10836                 new_hash += (unsigned)statb.st_mtime;
10837         }
10838         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10839                 if (mailtime_hash != 0)
10840                         out2str("you have mail\n");
10841                 mailtime_hash = new_hash;
10842         }
10843         mail_var_path_changed = 0;
10844         popstackmark(&smark);
10845 }
10846
10847 static void FAST_FUNC
10848 changemail(const char *val UNUSED_PARAM)
10849 {
10850         mail_var_path_changed = 1;
10851 }
10852
10853 #endif /* ASH_MAIL */
10854
10855
10856 /* ============ ??? */
10857
10858 /*
10859  * Set the shell parameters.
10860  */
10861 static void
10862 setparam(char **argv)
10863 {
10864         char **newparam;
10865         char **ap;
10866         int nparam;
10867
10868         for (nparam = 0; argv[nparam]; nparam++)
10869                 continue;
10870         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10871         while (*argv) {
10872                 *ap++ = ckstrdup(*argv++);
10873         }
10874         *ap = NULL;
10875         freeparam(&shellparam);
10876         shellparam.malloced = 1;
10877         shellparam.nparam = nparam;
10878         shellparam.p = newparam;
10879 #if ENABLE_ASH_GETOPTS
10880         shellparam.optind = 1;
10881         shellparam.optoff = -1;
10882 #endif
10883 }
10884
10885 /*
10886  * Process shell options.  The global variable argptr contains a pointer
10887  * to the argument list; we advance it past the options.
10888  *
10889  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10890  * For a non-interactive shell, an error condition encountered
10891  * by a special built-in ... shall cause the shell to write a diagnostic message
10892  * to standard error and exit as shown in the following table:
10893  * Error                                           Special Built-In
10894  * ...
10895  * Utility syntax error (option or operand error)  Shall exit
10896  * ...
10897  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10898  * we see that bash does not do that (set "finishes" with error code 1 instead,
10899  * and shell continues), and people rely on this behavior!
10900  * Testcase:
10901  * set -o barfoo 2>/dev/null
10902  * echo $?
10903  *
10904  * Oh well. Let's mimic that.
10905  */
10906 static int
10907 plus_minus_o(char *name, int val)
10908 {
10909         int i;
10910
10911         if (name) {
10912                 for (i = 0; i < NOPTS; i++) {
10913                         if (strcmp(name, optnames(i)) == 0) {
10914                                 optlist[i] = val;
10915                                 return 0;
10916                         }
10917                 }
10918                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10919                 return 1;
10920         }
10921         for (i = 0; i < NOPTS; i++) {
10922                 if (val) {
10923                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10924                 } else {
10925                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10926                 }
10927         }
10928         return 0;
10929 }
10930 static void
10931 setoption(int flag, int val)
10932 {
10933         int i;
10934
10935         for (i = 0; i < NOPTS; i++) {
10936                 if (optletters(i) == flag) {
10937                         optlist[i] = val;
10938                         return;
10939                 }
10940         }
10941         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10942         /* NOTREACHED */
10943 }
10944 static int
10945 options(int cmdline, int *login_sh)
10946 {
10947         char *p;
10948         int val;
10949         int c;
10950
10951         if (cmdline)
10952                 minusc = NULL;
10953         while ((p = *argptr) != NULL) {
10954                 c = *p++;
10955                 if (c != '-' && c != '+')
10956                         break;
10957                 argptr++;
10958                 val = 0; /* val = 0 if c == '+' */
10959                 if (c == '-') {
10960                         val = 1;
10961                         if (p[0] == '\0' || LONE_DASH(p)) {
10962                                 if (!cmdline) {
10963                                         /* "-" means turn off -x and -v */
10964                                         if (p[0] == '\0')
10965                                                 xflag = vflag = 0;
10966                                         /* "--" means reset params */
10967                                         else if (*argptr == NULL)
10968                                                 setparam(argptr);
10969                                 }
10970                                 break;    /* "-" or "--" terminates options */
10971                         }
10972                 }
10973                 /* first char was + or - */
10974                 while ((c = *p++) != '\0') {
10975                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10976                         if (c == 'c' && cmdline) {
10977                                 minusc = p;     /* command is after shell args */
10978                         } else if (c == 'o') {
10979                                 if (plus_minus_o(*argptr, val)) {
10980                                         /* it already printed err message */
10981                                         return 1; /* error */
10982                                 }
10983                                 if (*argptr)
10984                                         argptr++;
10985                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10986                                 if (login_sh)
10987                                         *login_sh = 1;
10988                         /* bash does not accept +-login, we also won't */
10989                         } else if (cmdline && val && (c == '-')) { /* long options */
10990                                 if (strcmp(p, "login") == 0) {
10991                                         if (login_sh)
10992                                                 *login_sh = 1;
10993                                 }
10994                                 break;
10995                         } else {
10996                                 setoption(c, val);
10997                         }
10998                 }
10999         }
11000         return 0;
11001 }
11002
11003 /*
11004  * The shift builtin command.
11005  */
11006 static int FAST_FUNC
11007 shiftcmd(int argc UNUSED_PARAM, char **argv)
11008 {
11009         int n;
11010         char **ap1, **ap2;
11011
11012         n = 1;
11013         if (argv[1])
11014                 n = number(argv[1]);
11015         if (n > shellparam.nparam)
11016                 return 1;
11017         INT_OFF;
11018         shellparam.nparam -= n;
11019         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11020                 if (shellparam.malloced)
11021                         free(*ap1);
11022         }
11023         ap2 = shellparam.p;
11024         while ((*ap2++ = *ap1++) != NULL)
11025                 continue;
11026 #if ENABLE_ASH_GETOPTS
11027         shellparam.optind = 1;
11028         shellparam.optoff = -1;
11029 #endif
11030         INT_ON;
11031         return 0;
11032 }
11033
11034 /*
11035  * POSIX requires that 'set' (but not export or readonly) output the
11036  * variables in lexicographic order - by the locale's collating order (sigh).
11037  * Maybe we could keep them in an ordered balanced binary tree
11038  * instead of hashed lists.
11039  * For now just roll 'em through qsort for printing...
11040  */
11041 static int
11042 showvars(const char *sep_prefix, int on, int off)
11043 {
11044         const char *sep;
11045         char **ep, **epend;
11046
11047         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11048         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11049
11050         sep = *sep_prefix ? " " : sep_prefix;
11051
11052         for (; ep < epend; ep++) {
11053                 const char *p;
11054                 const char *q;
11055
11056                 p = endofname(*ep);
11057 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11058  * makes "export -p" to have output not suitable for "eval":
11059  * import os
11060  * os.environ["test-test"]="test"
11061  * if os.fork() == 0:
11062  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11063  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11064  */
11065                 q = nullstr;
11066                 if (*p == '=')
11067                         q = single_quote(++p);
11068                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11069         }
11070         return 0;
11071 }
11072
11073 /*
11074  * The set command builtin.
11075  */
11076 static int FAST_FUNC
11077 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11078 {
11079         int retval;
11080
11081         if (!argv[1])
11082                 return showvars(nullstr, 0, VUNSET);
11083
11084         INT_OFF;
11085         retval = options(/*cmdline:*/ 0, NULL);
11086         if (retval == 0) { /* if no parse error... */
11087                 optschanged();
11088                 if (*argptr != NULL) {
11089                         setparam(argptr);
11090                 }
11091         }
11092         INT_ON;
11093         return retval;
11094 }
11095
11096 #if ENABLE_ASH_RANDOM_SUPPORT
11097 static void FAST_FUNC
11098 change_random(const char *value)
11099 {
11100         uint32_t t;
11101
11102         if (value == NULL) {
11103                 /* "get", generate */
11104                 t = next_random(&random_gen);
11105                 /* set without recursion */
11106                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11107                 vrandom.flags &= ~VNOFUNC;
11108         } else {
11109                 /* set/reset */
11110                 t = strtoul(value, NULL, 10);
11111                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11112         }
11113 }
11114 #endif
11115
11116 #if ENABLE_ASH_GETOPTS
11117 static int
11118 getopts(char *optstr, char *optvar, char **optfirst)
11119 {
11120         char *p, *q;
11121         char c = '?';
11122         int done = 0;
11123         char sbuf[2];
11124         char **optnext;
11125         int ind = shellparam.optind;
11126         int off = shellparam.optoff;
11127
11128         sbuf[1] = '\0';
11129
11130         shellparam.optind = -1;
11131         optnext = optfirst + ind - 1;
11132
11133         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11134                 p = NULL;
11135         else
11136                 p = optnext[-1] + off;
11137         if (p == NULL || *p == '\0') {
11138                 /* Current word is done, advance */
11139                 p = *optnext;
11140                 if (p == NULL || *p != '-' || *++p == '\0') {
11141  atend:
11142                         unsetvar("OPTARG");
11143                         p = NULL;
11144                         done = 1;
11145                         goto out;
11146                 }
11147                 optnext++;
11148                 if (LONE_DASH(p))        /* check for "--" */
11149                         goto atend;
11150         }
11151
11152         c = *p++;
11153         for (q = optstr; *q != c;) {
11154                 if (*q == '\0') {
11155                         /* OPTERR is a bashism */
11156                         const char *cp = lookupvar("OPTERR");
11157                         if ((cp && LONE_CHAR(cp, '0'))
11158                          || (optstr[0] == ':')
11159                         ) {
11160                                 sbuf[0] = c;
11161                                 /*sbuf[1] = '\0'; - already is */
11162                                 setvar0("OPTARG", sbuf);
11163                         } else {
11164                                 fprintf(stderr, "Illegal option -%c\n", c);
11165                                 unsetvar("OPTARG");
11166                         }
11167                         c = '?';
11168                         goto out;
11169                 }
11170                 if (*++q == ':')
11171                         q++;
11172         }
11173
11174         if (*++q == ':') {
11175                 if (*p == '\0' && (p = *optnext) == NULL) {
11176                         /* OPTERR is a bashism */
11177                         const char *cp = lookupvar("OPTERR");
11178                         if ((cp && LONE_CHAR(cp, '0'))
11179                          || (optstr[0] == ':')
11180                         ) {
11181                                 sbuf[0] = c;
11182                                 /*sbuf[1] = '\0'; - already is */
11183                                 setvar0("OPTARG", sbuf);
11184                                 c = ':';
11185                         } else {
11186                                 fprintf(stderr, "No arg for -%c option\n", c);
11187                                 unsetvar("OPTARG");
11188                                 c = '?';
11189                         }
11190                         goto out;
11191                 }
11192
11193                 if (p == *optnext)
11194                         optnext++;
11195                 setvar0("OPTARG", p);
11196                 p = NULL;
11197         } else
11198                 setvar0("OPTARG", nullstr);
11199  out:
11200         ind = optnext - optfirst + 1;
11201         setvar("OPTIND", itoa(ind), VNOFUNC);
11202         sbuf[0] = c;
11203         /*sbuf[1] = '\0'; - already is */
11204         setvar0(optvar, sbuf);
11205
11206         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11207         shellparam.optind = ind;
11208
11209         return done;
11210 }
11211
11212 /*
11213  * The getopts builtin.  Shellparam.optnext points to the next argument
11214  * to be processed.  Shellparam.optptr points to the next character to
11215  * be processed in the current argument.  If shellparam.optnext is NULL,
11216  * then it's the first time getopts has been called.
11217  */
11218 static int FAST_FUNC
11219 getoptscmd(int argc, char **argv)
11220 {
11221         char **optbase;
11222
11223         if (argc < 3)
11224                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11225         if (argc == 3) {
11226                 optbase = shellparam.p;
11227                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11228                         shellparam.optind = 1;
11229                         shellparam.optoff = -1;
11230                 }
11231         } else {
11232                 optbase = &argv[3];
11233                 if ((unsigned)shellparam.optind > argc - 2) {
11234                         shellparam.optind = 1;
11235                         shellparam.optoff = -1;
11236                 }
11237         }
11238
11239         return getopts(argv[1], argv[2], optbase);
11240 }
11241 #endif /* ASH_GETOPTS */
11242
11243
11244 /* ============ Shell parser */
11245
11246 struct heredoc {
11247         struct heredoc *next;   /* next here document in list */
11248         union node *here;       /* redirection node */
11249         char *eofmark;          /* string indicating end of input */
11250         smallint striptabs;     /* if set, strip leading tabs */
11251 };
11252
11253 static smallint tokpushback;           /* last token pushed back */
11254 static smallint quoteflag;             /* set if (part of) last token was quoted */
11255 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11256 static struct heredoc *heredoclist;    /* list of here documents to read */
11257 static char *wordtext;                 /* text of last word returned by readtoken */
11258 static struct nodelist *backquotelist;
11259 static union node *redirnode;
11260 static struct heredoc *heredoc;
11261
11262 static const char *
11263 tokname(char *buf, int tok)
11264 {
11265         if (tok < TSEMI)
11266                 return tokname_array[tok];
11267         sprintf(buf, "\"%s\"", tokname_array[tok]);
11268         return buf;
11269 }
11270
11271 /* raise_error_unexpected_syntax:
11272  * Called when an unexpected token is read during the parse.  The argument
11273  * is the token that is expected, or -1 if more than one type of token can
11274  * occur at this point.
11275  */
11276 static void raise_error_unexpected_syntax(int) NORETURN;
11277 static void
11278 raise_error_unexpected_syntax(int token)
11279 {
11280         char msg[64];
11281         char buf[16];
11282         int l;
11283
11284         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11285         if (token >= 0)
11286                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11287         raise_error_syntax(msg);
11288         /* NOTREACHED */
11289 }
11290
11291 /* parsing is heavily cross-recursive, need these forward decls */
11292 static union node *andor(void);
11293 static union node *pipeline(void);
11294 static union node *parse_command(void);
11295 static void parseheredoc(void);
11296 static int peektoken(void);
11297 static int readtoken(void);
11298
11299 static union node *
11300 list(int nlflag)
11301 {
11302         union node *n1, *n2, *n3;
11303         int tok;
11304
11305         n1 = NULL;
11306         for (;;) {
11307                 switch (peektoken()) {
11308                 case TNL:
11309                         if (!(nlflag & 1))
11310                                 break;
11311                         parseheredoc();
11312                         return n1;
11313
11314                 case TEOF:
11315                         if (!n1 && (nlflag & 1))
11316                                 n1 = NODE_EOF;
11317                         parseheredoc();
11318                         return n1;
11319                 }
11320
11321                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11322                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11323                         return n1;
11324                 nlflag |= 2;
11325
11326                 n2 = andor();
11327                 tok = readtoken();
11328                 if (tok == TBACKGND) {
11329                         if (n2->type == NPIPE) {
11330                                 n2->npipe.pipe_backgnd = 1;
11331                         } else {
11332                                 if (n2->type != NREDIR) {
11333                                         n3 = stzalloc(sizeof(struct nredir));
11334                                         n3->nredir.n = n2;
11335                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11336                                         n2 = n3;
11337                                 }
11338                                 n2->type = NBACKGND;
11339                         }
11340                 }
11341                 if (n1 == NULL) {
11342                         n1 = n2;
11343                 } else {
11344                         n3 = stzalloc(sizeof(struct nbinary));
11345                         n3->type = NSEMI;
11346                         n3->nbinary.ch1 = n1;
11347                         n3->nbinary.ch2 = n2;
11348                         n1 = n3;
11349                 }
11350                 switch (tok) {
11351                 case TNL:
11352                 case TEOF:
11353                         tokpushback = 1;
11354                         /* fall through */
11355                 case TBACKGND:
11356                 case TSEMI:
11357                         break;
11358                 default:
11359                         if ((nlflag & 1))
11360                                 raise_error_unexpected_syntax(-1);
11361                         tokpushback = 1;
11362                         return n1;
11363                 }
11364         }
11365 }
11366
11367 static union node *
11368 andor(void)
11369 {
11370         union node *n1, *n2, *n3;
11371         int t;
11372
11373         n1 = pipeline();
11374         for (;;) {
11375                 t = readtoken();
11376                 if (t == TAND) {
11377                         t = NAND;
11378                 } else if (t == TOR) {
11379                         t = NOR;
11380                 } else {
11381                         tokpushback = 1;
11382                         return n1;
11383                 }
11384                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11385                 n2 = pipeline();
11386                 n3 = stzalloc(sizeof(struct nbinary));
11387                 n3->type = t;
11388                 n3->nbinary.ch1 = n1;
11389                 n3->nbinary.ch2 = n2;
11390                 n1 = n3;
11391         }
11392 }
11393
11394 static union node *
11395 pipeline(void)
11396 {
11397         union node *n1, *n2, *pipenode;
11398         struct nodelist *lp, *prev;
11399         int negate;
11400
11401         negate = 0;
11402         TRACE(("pipeline: entered\n"));
11403         if (readtoken() == TNOT) {
11404                 negate = !negate;
11405                 checkkwd = CHKKWD | CHKALIAS;
11406         } else
11407                 tokpushback = 1;
11408         n1 = parse_command();
11409         if (readtoken() == TPIPE) {
11410                 pipenode = stzalloc(sizeof(struct npipe));
11411                 pipenode->type = NPIPE;
11412                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11413                 lp = stzalloc(sizeof(struct nodelist));
11414                 pipenode->npipe.cmdlist = lp;
11415                 lp->n = n1;
11416                 do {
11417                         prev = lp;
11418                         lp = stzalloc(sizeof(struct nodelist));
11419                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11420                         lp->n = parse_command();
11421                         prev->next = lp;
11422                 } while (readtoken() == TPIPE);
11423                 lp->next = NULL;
11424                 n1 = pipenode;
11425         }
11426         tokpushback = 1;
11427         if (negate) {
11428                 n2 = stzalloc(sizeof(struct nnot));
11429                 n2->type = NNOT;
11430                 n2->nnot.com = n1;
11431                 return n2;
11432         }
11433         return n1;
11434 }
11435
11436 static union node *
11437 makename(void)
11438 {
11439         union node *n;
11440
11441         n = stzalloc(sizeof(struct narg));
11442         n->type = NARG;
11443         /*n->narg.next = NULL; - stzalloc did it */
11444         n->narg.text = wordtext;
11445         n->narg.backquote = backquotelist;
11446         return n;
11447 }
11448
11449 static void
11450 fixredir(union node *n, const char *text, int err)
11451 {
11452         int fd;
11453
11454         TRACE(("Fix redir %s %d\n", text, err));
11455         if (!err)
11456                 n->ndup.vname = NULL;
11457
11458         fd = bb_strtou(text, NULL, 10);
11459         if (!errno && fd >= 0)
11460                 n->ndup.dupfd = fd;
11461         else if (LONE_DASH(text))
11462                 n->ndup.dupfd = -1;
11463         else {
11464                 if (err)
11465                         raise_error_syntax("bad fd number");
11466                 n->ndup.vname = makename();
11467         }
11468 }
11469
11470 static void
11471 parsefname(void)
11472 {
11473         union node *n = redirnode;
11474
11475         if (n->type == NHERE)
11476                 checkkwd = CHKEOFMARK;
11477         if (readtoken() != TWORD)
11478                 raise_error_unexpected_syntax(-1);
11479         if (n->type == NHERE) {
11480                 struct heredoc *here = heredoc;
11481                 struct heredoc *p;
11482
11483                 if (quoteflag == 0)
11484                         n->type = NXHERE;
11485                 TRACE(("Here document %d\n", n->type));
11486                 rmescapes(wordtext, 0, NULL);
11487                 here->eofmark = wordtext;
11488                 here->next = NULL;
11489                 if (heredoclist == NULL)
11490                         heredoclist = here;
11491                 else {
11492                         for (p = heredoclist; p->next; p = p->next)
11493                                 continue;
11494                         p->next = here;
11495                 }
11496         } else if (n->type == NTOFD || n->type == NFROMFD) {
11497                 fixredir(n, wordtext, 0);
11498         } else {
11499                 n->nfile.fname = makename();
11500         }
11501 }
11502
11503 static union node *
11504 simplecmd(void)
11505 {
11506         union node *args, **app;
11507         union node *n = NULL;
11508         union node *vars, **vpp;
11509         union node **rpp, *redir;
11510         int savecheckkwd;
11511         int savelinno;
11512 #if BASH_TEST2
11513         smallint double_brackets_flag = 0;
11514 #endif
11515         IF_BASH_FUNCTION(smallint function_flag = 0;)
11516
11517         args = NULL;
11518         app = &args;
11519         vars = NULL;
11520         vpp = &vars;
11521         redir = NULL;
11522         rpp = &redir;
11523
11524         savecheckkwd = CHKALIAS;
11525         savelinno = g_parsefile->linno;
11526         for (;;) {
11527                 int t;
11528                 checkkwd = savecheckkwd;
11529                 t = readtoken();
11530                 switch (t) {
11531 #if BASH_FUNCTION
11532                 case TFUNCTION:
11533                         if (peektoken() != TWORD)
11534                                 raise_error_unexpected_syntax(TWORD);
11535                         function_flag = 1;
11536                         break;
11537 #endif
11538 #if BASH_TEST2
11539                 case TAND: /* "&&" */
11540                 case TOR: /* "||" */
11541                         if (!double_brackets_flag) {
11542                                 tokpushback = 1;
11543                                 goto out;
11544                         }
11545                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11546 #endif
11547                 case TWORD:
11548                         n = stzalloc(sizeof(struct narg));
11549                         n->type = NARG;
11550                         /*n->narg.next = NULL; - stzalloc did it */
11551                         n->narg.text = wordtext;
11552 #if BASH_TEST2
11553                         if (strcmp("[[", wordtext) == 0)
11554                                 double_brackets_flag = 1;
11555                         else if (strcmp("]]", wordtext) == 0)
11556                                 double_brackets_flag = 0;
11557 #endif
11558                         n->narg.backquote = backquotelist;
11559                         if (savecheckkwd && isassignment(wordtext)) {
11560                                 *vpp = n;
11561                                 vpp = &n->narg.next;
11562                         } else {
11563                                 *app = n;
11564                                 app = &n->narg.next;
11565                                 savecheckkwd = 0;
11566                         }
11567 #if BASH_FUNCTION
11568                         if (function_flag) {
11569                                 checkkwd = CHKNL | CHKKWD;
11570                                 switch (peektoken()) {
11571                                 case TBEGIN:
11572                                 case TIF:
11573                                 case TCASE:
11574                                 case TUNTIL:
11575                                 case TWHILE:
11576                                 case TFOR:
11577                                         goto do_func;
11578                                 case TLP:
11579                                         function_flag = 0;
11580                                         break;
11581                                 case TWORD:
11582                                         if (strcmp("[[", wordtext) == 0)
11583                                                 goto do_func;
11584                                         /* fall through */
11585                                 default:
11586                                         raise_error_unexpected_syntax(-1);
11587                                 }
11588                         }
11589 #endif
11590                         break;
11591                 case TREDIR:
11592                         *rpp = n = redirnode;
11593                         rpp = &n->nfile.next;
11594                         parsefname();   /* read name of redirection file */
11595                         break;
11596                 case TLP:
11597  IF_BASH_FUNCTION(do_func:)
11598                         if (args && app == &args->narg.next
11599                          && !vars && !redir
11600                         ) {
11601                                 struct builtincmd *bcmd;
11602                                 const char *name;
11603
11604                                 /* We have a function */
11605                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11606                                         raise_error_unexpected_syntax(TRP);
11607                                 name = n->narg.text;
11608                                 if (!goodname(name)
11609                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11610                                 ) {
11611                                         raise_error_syntax("bad function name");
11612                                 }
11613                                 n->type = NDEFUN;
11614                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11615                                 n->ndefun.text = n->narg.text;
11616                                 n->ndefun.linno = g_parsefile->linno;
11617                                 n->ndefun.body = parse_command();
11618                                 return n;
11619                         }
11620                         IF_BASH_FUNCTION(function_flag = 0;)
11621                         /* fall through */
11622                 default:
11623                         tokpushback = 1;
11624                         goto out;
11625                 }
11626         }
11627  out:
11628         *app = NULL;
11629         *vpp = NULL;
11630         *rpp = NULL;
11631         n = stzalloc(sizeof(struct ncmd));
11632         n->type = NCMD;
11633         n->ncmd.linno = savelinno;
11634         n->ncmd.args = args;
11635         n->ncmd.assign = vars;
11636         n->ncmd.redirect = redir;
11637         return n;
11638 }
11639
11640 static union node *
11641 parse_command(void)
11642 {
11643         union node *n1, *n2;
11644         union node *ap, **app;
11645         union node *cp, **cpp;
11646         union node *redir, **rpp;
11647         union node **rpp2;
11648         int t;
11649         int savelinno;
11650
11651         redir = NULL;
11652         rpp2 = &redir;
11653
11654         savelinno = g_parsefile->linno;
11655
11656         switch (readtoken()) {
11657         default:
11658                 raise_error_unexpected_syntax(-1);
11659                 /* NOTREACHED */
11660         case TIF:
11661                 n1 = stzalloc(sizeof(struct nif));
11662                 n1->type = NIF;
11663                 n1->nif.test = list(0);
11664                 if (readtoken() != TTHEN)
11665                         raise_error_unexpected_syntax(TTHEN);
11666                 n1->nif.ifpart = list(0);
11667                 n2 = n1;
11668                 while (readtoken() == TELIF) {
11669                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11670                         n2 = n2->nif.elsepart;
11671                         n2->type = NIF;
11672                         n2->nif.test = list(0);
11673                         if (readtoken() != TTHEN)
11674                                 raise_error_unexpected_syntax(TTHEN);
11675                         n2->nif.ifpart = list(0);
11676                 }
11677                 if (lasttoken == TELSE)
11678                         n2->nif.elsepart = list(0);
11679                 else {
11680                         n2->nif.elsepart = NULL;
11681                         tokpushback = 1;
11682                 }
11683                 t = TFI;
11684                 break;
11685         case TWHILE:
11686         case TUNTIL: {
11687                 int got;
11688                 n1 = stzalloc(sizeof(struct nbinary));
11689                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11690                 n1->nbinary.ch1 = list(0);
11691                 got = readtoken();
11692                 if (got != TDO) {
11693                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11694                                         got == TWORD ? wordtext : ""));
11695                         raise_error_unexpected_syntax(TDO);
11696                 }
11697                 n1->nbinary.ch2 = list(0);
11698                 t = TDONE;
11699                 break;
11700         }
11701         case TFOR:
11702                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11703                         raise_error_syntax("bad for loop variable");
11704                 n1 = stzalloc(sizeof(struct nfor));
11705                 n1->type = NFOR;
11706                 n1->nfor.linno = savelinno;
11707                 n1->nfor.var = wordtext;
11708                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11709                 if (readtoken() == TIN) {
11710                         app = &ap;
11711                         while (readtoken() == TWORD) {
11712                                 n2 = stzalloc(sizeof(struct narg));
11713                                 n2->type = NARG;
11714                                 /*n2->narg.next = NULL; - stzalloc did it */
11715                                 n2->narg.text = wordtext;
11716                                 n2->narg.backquote = backquotelist;
11717                                 *app = n2;
11718                                 app = &n2->narg.next;
11719                         }
11720                         *app = NULL;
11721                         n1->nfor.args = ap;
11722                         if (lasttoken != TNL && lasttoken != TSEMI)
11723                                 raise_error_unexpected_syntax(-1);
11724                 } else {
11725                         n2 = stzalloc(sizeof(struct narg));
11726                         n2->type = NARG;
11727                         /*n2->narg.next = NULL; - stzalloc did it */
11728                         n2->narg.text = (char *)dolatstr;
11729                         /*n2->narg.backquote = NULL;*/
11730                         n1->nfor.args = n2;
11731                         /*
11732                          * Newline or semicolon here is optional (but note
11733                          * that the original Bourne shell only allowed NL).
11734                          */
11735                         if (lasttoken != TSEMI)
11736                                 tokpushback = 1;
11737                 }
11738                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11739                 if (readtoken() != TDO)
11740                         raise_error_unexpected_syntax(TDO);
11741                 n1->nfor.body = list(0);
11742                 t = TDONE;
11743                 break;
11744         case TCASE:
11745                 n1 = stzalloc(sizeof(struct ncase));
11746                 n1->type = NCASE;
11747                 n1->ncase.linno = savelinno;
11748                 if (readtoken() != TWORD)
11749                         raise_error_unexpected_syntax(TWORD);
11750                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11751                 n2->type = NARG;
11752                 /*n2->narg.next = NULL; - stzalloc did it */
11753                 n2->narg.text = wordtext;
11754                 n2->narg.backquote = backquotelist;
11755                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11756                 if (readtoken() != TIN)
11757                         raise_error_unexpected_syntax(TIN);
11758                 cpp = &n1->ncase.cases;
11759  next_case:
11760                 checkkwd = CHKNL | CHKKWD;
11761                 t = readtoken();
11762                 while (t != TESAC) {
11763                         if (lasttoken == TLP)
11764                                 readtoken();
11765                         *cpp = cp = stzalloc(sizeof(struct nclist));
11766                         cp->type = NCLIST;
11767                         app = &cp->nclist.pattern;
11768                         for (;;) {
11769                                 *app = ap = stzalloc(sizeof(struct narg));
11770                                 ap->type = NARG;
11771                                 /*ap->narg.next = NULL; - stzalloc did it */
11772                                 ap->narg.text = wordtext;
11773                                 ap->narg.backquote = backquotelist;
11774                                 if (readtoken() != TPIPE)
11775                                         break;
11776                                 app = &ap->narg.next;
11777                                 readtoken();
11778                         }
11779                         //ap->narg.next = NULL;
11780                         if (lasttoken != TRP)
11781                                 raise_error_unexpected_syntax(TRP);
11782                         cp->nclist.body = list(2);
11783
11784                         cpp = &cp->nclist.next;
11785
11786                         checkkwd = CHKNL | CHKKWD;
11787                         t = readtoken();
11788                         if (t != TESAC) {
11789                                 if (t != TENDCASE)
11790                                         raise_error_unexpected_syntax(TENDCASE);
11791                                 goto next_case;
11792                         }
11793                 }
11794                 *cpp = NULL;
11795                 goto redir;
11796         case TLP:
11797                 n1 = stzalloc(sizeof(struct nredir));
11798                 n1->type = NSUBSHELL;
11799                 n1->nredir.linno = savelinno;
11800                 n1->nredir.n = list(0);
11801                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11802                 t = TRP;
11803                 break;
11804         case TBEGIN:
11805                 n1 = list(0);
11806                 t = TEND;
11807                 break;
11808         IF_BASH_FUNCTION(case TFUNCTION:)
11809         case TWORD:
11810         case TREDIR:
11811                 tokpushback = 1;
11812                 return simplecmd();
11813         }
11814
11815         if (readtoken() != t)
11816                 raise_error_unexpected_syntax(t);
11817
11818  redir:
11819         /* Now check for redirection which may follow command */
11820         checkkwd = CHKKWD | CHKALIAS;
11821         rpp = rpp2;
11822         while (readtoken() == TREDIR) {
11823                 *rpp = n2 = redirnode;
11824                 rpp = &n2->nfile.next;
11825                 parsefname();
11826         }
11827         tokpushback = 1;
11828         *rpp = NULL;
11829         if (redir) {
11830                 if (n1->type != NSUBSHELL) {
11831                         n2 = stzalloc(sizeof(struct nredir));
11832                         n2->type = NREDIR;
11833                         n2->nredir.linno = savelinno;
11834                         n2->nredir.n = n1;
11835                         n1 = n2;
11836                 }
11837                 n1->nredir.redirect = redir;
11838         }
11839         return n1;
11840 }
11841
11842 #if BASH_DOLLAR_SQUOTE
11843 static int
11844 decode_dollar_squote(void)
11845 {
11846         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11847         int c, cnt;
11848         char *p;
11849         char buf[4];
11850
11851         c = pgetc();
11852         p = strchr(C_escapes, c);
11853         if (p) {
11854                 buf[0] = c;
11855                 p = buf;
11856                 cnt = 3;
11857                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11858                         do {
11859                                 c = pgetc();
11860                                 *++p = c;
11861                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11862                         pungetc();
11863                 } else if (c == 'x') { /* \xHH */
11864                         do {
11865                                 c = pgetc();
11866                                 *++p = c;
11867                         } while (isxdigit(c) && --cnt);
11868                         pungetc();
11869                         if (cnt == 3) { /* \x but next char is "bad" */
11870                                 c = 'x';
11871                                 goto unrecognized;
11872                         }
11873                 } else { /* simple seq like \\ or \t */
11874                         p++;
11875                 }
11876                 *p = '\0';
11877                 p = buf;
11878                 c = bb_process_escape_sequence((void*)&p);
11879         } else { /* unrecognized "\z": print both chars unless ' or " */
11880                 if (c != '\'' && c != '"') {
11881  unrecognized:
11882                         c |= 0x100; /* "please encode \, then me" */
11883                 }
11884         }
11885         return c;
11886 }
11887 #endif
11888
11889 /* Used by expandstr to get here-doc like behaviour. */
11890 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11891
11892 static ALWAYS_INLINE int
11893 realeofmark(const char *eofmark)
11894 {
11895         return eofmark && eofmark != FAKEEOFMARK;
11896 }
11897
11898 /*
11899  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11900  * is not NULL, read a here document.  In the latter case, eofmark is the
11901  * word which marks the end of the document and striptabs is true if
11902  * leading tabs should be stripped from the document.  The argument c
11903  * is the first character of the input token or document.
11904  *
11905  * Because C does not have internal subroutines, I have simulated them
11906  * using goto's to implement the subroutine linkage.  The following macros
11907  * will run code that appears at the end of readtoken1.
11908  */
11909 #define CHECKEND()      {goto checkend; checkend_return:;}
11910 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11911 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11912 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11913 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11914 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11915 static int
11916 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11917 {
11918         /* NB: syntax parameter fits into smallint */
11919         /* c parameter is an unsigned char or PEOF or PEOA */
11920         char *out;
11921         size_t len;
11922         struct nodelist *bqlist;
11923         smallint quotef;
11924         smallint dblquote;
11925         smallint oldstyle;
11926         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11927         smallint pssyntax;   /* we are expanding a prompt string */
11928         int varnest;         /* levels of variables expansion */
11929         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11930         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11931         int dqvarnest;       /* levels of variables expansion within double quotes */
11932         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11933
11934         bqlist = NULL;
11935         quotef = 0;
11936         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11937 #if ENABLE_ASH_EXPAND_PRMT
11938         pssyntax = (syntax == PSSYNTAX);
11939         if (pssyntax)
11940                 syntax = DQSYNTAX;
11941 #else
11942         pssyntax = 0; /* constant */
11943 #endif
11944         dblquote = (syntax == DQSYNTAX);
11945         varnest = 0;
11946         IF_FEATURE_SH_MATH(arinest = 0;)
11947         IF_FEATURE_SH_MATH(parenlevel = 0;)
11948         dqvarnest = 0;
11949
11950         STARTSTACKSTR(out);
11951  loop:
11952         /* For each line, until end of word */
11953         CHECKEND();     /* set c to PEOF if at end of here document */
11954         for (;;) {      /* until end of line or end of word */
11955                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11956                 switch (SIT(c, syntax)) {
11957                 case CNL:       /* '\n' */
11958                         if (syntax == BASESYNTAX)
11959                                 goto endword;   /* exit outer loop */
11960                         USTPUTC(c, out);
11961                         nlprompt();
11962                         c = pgetc();
11963                         goto loop;              /* continue outer loop */
11964                 case CWORD:
11965                         USTPUTC(c, out);
11966                         break;
11967                 case CCTL:
11968 #if BASH_DOLLAR_SQUOTE
11969                         if (c == '\\' && bash_dollar_squote) {
11970                                 c = decode_dollar_squote();
11971                                 if (c == '\0') {
11972                                         /* skip $'\000', $'\x00' (like bash) */
11973                                         break;
11974                                 }
11975                                 if (c & 0x100) {
11976                                         /* Unknown escape. Encode as '\z' */
11977                                         c = (unsigned char)c;
11978                                         if (eofmark == NULL || dblquote)
11979                                                 USTPUTC(CTLESC, out);
11980                                         USTPUTC('\\', out);
11981                                 }
11982                         }
11983 #endif
11984                         if (eofmark == NULL || dblquote)
11985                                 USTPUTC(CTLESC, out);
11986                         USTPUTC(c, out);
11987                         break;
11988                 case CBACK:     /* backslash */
11989                         c = pgetc_without_PEOA();
11990                         if (c == PEOF) {
11991                                 USTPUTC(CTLESC, out);
11992                                 USTPUTC('\\', out);
11993                                 pungetc();
11994                         } else if (c == '\n') {
11995                                 nlprompt();
11996                         } else {
11997                                 if (pssyntax && c == '$') {
11998                                         USTPUTC(CTLESC, out);
11999                                         USTPUTC('\\', out);
12000                                 }
12001                                 /* Backslash is retained if we are in "str"
12002                                  * and next char isn't dquote-special.
12003                                  */
12004                                 if (dblquote
12005                                  && c != '\\'
12006                                  && c != '`'
12007                                  && c != '$'
12008                                  && (c != '"' || eofmark != NULL)
12009                                 ) {
12010 //dash survives not doing USTPUTC(CTLESC), but merely by chance:
12011 //Example: "\z" gets encoded as "\<CTLESC>z".
12012 //rmescapes() then emits "\", "\z", protecting z from globbing.
12013 //But it's wrong, should protect _both_ from globbing:
12014 //everything in double quotes is not globbed.
12015 //Unlike dash, we have a fix in rmescapes() which emits bare "z"
12016 //for "<CTLESC>z" since "z" is not glob-special (else unicode may break),
12017 //and glob would see "\z" and eat "\". Thus:
12018                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12019                                         USTPUTC('\\', out);
12020                                 }
12021                                 USTPUTC(CTLESC, out);
12022                                 USTPUTC(c, out);
12023                                 quotef = 1;
12024                         }
12025                         break;
12026                 case CSQUOTE:
12027                         syntax = SQSYNTAX;
12028  quotemark:
12029                         if (eofmark == NULL) {
12030                                 USTPUTC(CTLQUOTEMARK, out);
12031                         }
12032                         break;
12033                 case CDQUOTE:
12034                         syntax = DQSYNTAX;
12035                         dblquote = 1;
12036                         goto quotemark;
12037                 case CENDQUOTE:
12038                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12039                         if (eofmark != NULL && varnest == 0) {
12040                                 USTPUTC(c, out);
12041                         } else {
12042                                 if (dqvarnest == 0) {
12043                                         syntax = BASESYNTAX;
12044                                         dblquote = 0;
12045                                 }
12046                                 quotef = 1;
12047                                 goto quotemark;
12048                         }
12049                         break;
12050                 case CVAR:      /* '$' */
12051                         PARSESUB();             /* parse substitution */
12052                         break;
12053                 case CENDVAR:   /* '}' */
12054                         if (varnest > 0) {
12055                                 varnest--;
12056                                 if (dqvarnest > 0) {
12057                                         dqvarnest--;
12058                                 }
12059                                 c = CTLENDVAR;
12060                         }
12061                         USTPUTC(c, out);
12062                         break;
12063 #if ENABLE_FEATURE_SH_MATH
12064                 case CLP:       /* '(' in arithmetic */
12065                         parenlevel++;
12066                         USTPUTC(c, out);
12067                         break;
12068                 case CRP:       /* ')' in arithmetic */
12069                         if (parenlevel > 0) {
12070                                 parenlevel--;
12071                         } else {
12072                                 if (pgetc_eatbnl() == ')') {
12073                                         c = CTLENDARI;
12074                                         if (--arinest == 0) {
12075                                                 syntax = prevsyntax;
12076                                         }
12077                                 } else {
12078                                         /*
12079                                          * unbalanced parens
12080                                          * (don't 2nd guess - no error)
12081                                          */
12082                                         pungetc();
12083                                 }
12084                         }
12085                         USTPUTC(c, out);
12086                         break;
12087 #endif
12088                 case CBQUOTE:   /* '`' */
12089                         PARSEBACKQOLD();
12090                         break;
12091                 case CENDFILE:
12092                         goto endword;           /* exit outer loop */
12093                 case CIGN:
12094                         break;
12095                 default:
12096                         if (varnest == 0) {
12097 #if BASH_REDIR_OUTPUT
12098                                 if (c == '&') {
12099 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12100                                         if (pgetc() == '>')
12101                                                 c = 0x100 + '>'; /* flag &> */
12102                                         pungetc();
12103                                 }
12104 #endif
12105                                 goto endword;   /* exit outer loop */
12106                         }
12107                         IF_ASH_ALIAS(if (c != PEOA))
12108                                 USTPUTC(c, out);
12109                 }
12110                 c = pgetc();
12111         } /* for (;;) */
12112  endword:
12113
12114 #if ENABLE_FEATURE_SH_MATH
12115         if (syntax == ARISYNTAX)
12116                 raise_error_syntax("missing '))'");
12117 #endif
12118         if (syntax != BASESYNTAX && eofmark == NULL)
12119                 raise_error_syntax("unterminated quoted string");
12120         if (varnest != 0) {
12121                 /* { */
12122                 raise_error_syntax("missing '}'");
12123         }
12124         USTPUTC('\0', out);
12125         len = out - (char *)stackblock();
12126         out = stackblock();
12127         if (eofmark == NULL) {
12128                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12129                  && quotef == 0
12130                 ) {
12131                         if (isdigit_str9(out)) {
12132                                 PARSEREDIR(); /* passed as params: out, c */
12133                                 lasttoken = TREDIR;
12134                                 return lasttoken;
12135                         }
12136                         /* else: non-number X seen, interpret it
12137                          * as "NNNX>file" = "NNNX >file" */
12138                 }
12139                 pungetc();
12140         }
12141         quoteflag = quotef;
12142         backquotelist = bqlist;
12143         grabstackblock(len);
12144         wordtext = out;
12145         lasttoken = TWORD;
12146         return lasttoken;
12147 /* end of readtoken routine */
12148
12149 /*
12150  * Check to see whether we are at the end of the here document.  When this
12151  * is called, c is set to the first character of the next input line.  If
12152  * we are at the end of the here document, this routine sets the c to PEOF.
12153  */
12154 checkend: {
12155         if (realeofmark(eofmark)) {
12156                 int markloc;
12157                 char *p;
12158
12159 #if ENABLE_ASH_ALIAS
12160                 if (c == PEOA)
12161                         c = pgetc_without_PEOA();
12162 #endif
12163                 if (striptabs) {
12164                         while (c == '\t') {
12165                                 c = pgetc_without_PEOA();
12166                         }
12167                 }
12168
12169                 markloc = out - (char *)stackblock();
12170                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12171                         if (c != *p)
12172                                 goto more_heredoc;
12173
12174                         c = pgetc_without_PEOA();
12175                 }
12176
12177                 if (c == '\n' || c == PEOF) {
12178                         c = PEOF;
12179                         g_parsefile->linno++;
12180                         needprompt = doprompt;
12181                 } else {
12182                         int len_here;
12183
12184  more_heredoc:
12185                         p = (char *)stackblock() + markloc + 1;
12186                         len_here = out - p;
12187
12188                         if (len_here) {
12189                                 len_here -= (c >= PEOF);
12190                                 c = p[-1];
12191
12192                                 if (len_here) {
12193                                         char *str;
12194
12195                                         str = alloca(len_here + 1);
12196                                         *(char *)mempcpy(str, p, len_here) = '\0';
12197
12198                                         pushstring(str, NULL);
12199                                 }
12200                         }
12201                 }
12202
12203                 STADJUST((char *)stackblock() + markloc - out, out);
12204         }
12205         goto checkend_return;
12206 }
12207
12208 /*
12209  * Parse a redirection operator.  The variable "out" points to a string
12210  * specifying the fd to be redirected.  The variable "c" contains the
12211  * first character of the redirection operator.
12212  */
12213 parseredir: {
12214         /* out is already checked to be a valid number or "" */
12215         int fd = (*out == '\0' ? -1 : atoi(out));
12216         union node *np;
12217
12218         np = stzalloc(sizeof(struct nfile));
12219         if (c == '>') {
12220                 np->nfile.fd = 1;
12221                 c = pgetc();
12222                 if (c == '>')
12223                         np->type = NAPPEND;
12224                 else if (c == '|')
12225                         np->type = NCLOBBER;
12226                 else if (c == '&')
12227                         np->type = NTOFD;
12228                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12229                 else {
12230                         np->type = NTO;
12231                         pungetc();
12232                 }
12233         }
12234 #if BASH_REDIR_OUTPUT
12235         else if (c == 0x100 + '>') { /* this flags &> redirection */
12236                 np->nfile.fd = 1;
12237                 pgetc(); /* this is '>', no need to check */
12238                 np->type = NTO2;
12239         }
12240 #endif
12241         else { /* c == '<' */
12242                 /*np->nfile.fd = 0; - stzalloc did it */
12243                 c = pgetc();
12244                 switch (c) {
12245                 case '<':
12246                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12247                                 np = stzalloc(sizeof(struct nhere));
12248                                 /*np->nfile.fd = 0; - stzalloc did it */
12249                         }
12250                         np->type = NHERE;
12251                         heredoc = stzalloc(sizeof(struct heredoc));
12252                         heredoc->here = np;
12253                         c = pgetc();
12254                         if (c == '-') {
12255                                 heredoc->striptabs = 1;
12256                         } else {
12257                                 /*heredoc->striptabs = 0; - stzalloc did it */
12258                                 pungetc();
12259                         }
12260                         break;
12261
12262                 case '&':
12263                         np->type = NFROMFD;
12264                         break;
12265
12266                 case '>':
12267                         np->type = NFROMTO;
12268                         break;
12269
12270                 default:
12271                         np->type = NFROM;
12272                         pungetc();
12273                         break;
12274                 }
12275         }
12276         if (fd >= 0)
12277                 np->nfile.fd = fd;
12278         redirnode = np;
12279         goto parseredir_return;
12280 }
12281
12282 /*
12283  * Parse a substitution.  At this point, we have read the dollar sign
12284  * and nothing else.
12285  */
12286
12287 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12288  * (assuming ascii char codes, as the original implementation did) */
12289 #define is_special(c) \
12290         (((unsigned)(c) - 33 < 32) \
12291                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12292 parsesub: {
12293         unsigned char subtype;
12294         int typeloc;
12295
12296         c = pgetc_eatbnl();
12297         if ((checkkwd & CHKEOFMARK)
12298          || c > 255 /* PEOA or PEOF */
12299          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12300         ) {
12301 #if BASH_DOLLAR_SQUOTE
12302                 if (syntax != DQSYNTAX && c == '\'')
12303                         bash_dollar_squote = 1;
12304                 else
12305 #endif
12306                         USTPUTC('$', out);
12307                 pungetc();
12308         } else if (c == '(') {
12309                 /* $(command) or $((arith)) */
12310                 if (pgetc_eatbnl() == '(') {
12311 #if ENABLE_FEATURE_SH_MATH
12312                         PARSEARITH();
12313 #else
12314                         raise_error_syntax("support for $((arith)) is disabled");
12315 #endif
12316                 } else {
12317                         pungetc();
12318                         PARSEBACKQNEW();
12319                 }
12320         } else {
12321                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12322                 USTPUTC(CTLVAR, out);
12323                 typeloc = out - (char *)stackblock();
12324                 STADJUST(1, out);
12325                 subtype = VSNORMAL;
12326                 if (c == '{') {
12327                         c = pgetc_eatbnl();
12328                         subtype = 0;
12329                 }
12330  varname:
12331                 if (is_name(c)) {
12332                         /* $[{[#]]NAME[}] */
12333                         do {
12334                                 STPUTC(c, out);
12335                                 c = pgetc_eatbnl();
12336                         } while (is_in_name(c));
12337                 } else if (isdigit(c)) {
12338                         /* $[{[#]]NUM[}] */
12339                         do {
12340                                 STPUTC(c, out);
12341                                 c = pgetc_eatbnl();
12342                         } while (isdigit(c));
12343                 } else {
12344                         /* $[{[#]]<specialchar>[}] */
12345                         int cc = c;
12346
12347                         c = pgetc_eatbnl();
12348                         if (!subtype && cc == '#') {
12349                                 subtype = VSLENGTH;
12350                                 if (c == '_' || isalnum(c))
12351                                         goto varname;
12352                                 cc = c;
12353                                 c = pgetc_eatbnl();
12354                                 if (cc == '}' || c != '}') {
12355                                         pungetc();
12356                                         subtype = 0;
12357                                         c = cc;
12358                                         cc = '#';
12359                                 }
12360                         }
12361
12362                         if (!is_special(cc)) {
12363                                 if (subtype == VSLENGTH)
12364                                         subtype = 0;
12365                                 goto badsub;
12366                         }
12367
12368                         USTPUTC(cc, out);
12369                 }
12370
12371                 if (c != '}' && subtype == VSLENGTH) {
12372                         /* ${#VAR didn't end with } */
12373                         goto badsub;
12374                 }
12375
12376                 if (subtype == 0) {
12377                         static const char types[] ALIGN1 = "}-+?=";
12378                         /* ${VAR...} but not $VAR or ${#VAR} */
12379                         /* c == first char after VAR */
12380                         switch (c) {
12381                         case ':':
12382                                 c = pgetc_eatbnl();
12383 #if BASH_SUBSTR
12384                                 /* This check is only needed to not misinterpret
12385                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12386                                  * constructs.
12387                                  */
12388                                 if (!strchr(types, c)) {
12389                                         subtype = VSSUBSTR;
12390                                         pungetc();
12391                                         break; /* "goto badsub" is bigger (!) */
12392                                 }
12393 #endif
12394                                 subtype = VSNUL;
12395                                 /*FALLTHROUGH*/
12396                         default: {
12397                                 const char *p = strchr(types, c);
12398                                 if (p == NULL)
12399                                         break;
12400                                 subtype |= p - types + VSNORMAL;
12401                                 break;
12402                         }
12403                         case '%':
12404                         case '#': {
12405                                 int cc = c;
12406                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12407                                 c = pgetc_eatbnl();
12408                                 if (c != cc)
12409                                         goto badsub;
12410                                 subtype++;
12411                                 break;
12412                         }
12413 #if BASH_PATTERN_SUBST
12414                         case '/':
12415                                 /* ${v/[/]pattern/repl} */
12416 //TODO: encode pattern and repl separately.
12417 // Currently ${v/$var_with_slash/repl} is horribly broken
12418                                 subtype = VSREPLACE;
12419                                 c = pgetc_eatbnl();
12420                                 if (c != '/')
12421                                         goto badsub;
12422                                 subtype++; /* VSREPLACEALL */
12423                                 break;
12424 #endif
12425                         }
12426                 } else {
12427  badsub:
12428                         pungetc();
12429                 }
12430                 ((unsigned char *)stackblock())[typeloc] = subtype;
12431                 if (subtype != VSNORMAL) {
12432                         varnest++;
12433                         if (dblquote)
12434                                 dqvarnest++;
12435                 }
12436                 STPUTC('=', out);
12437         }
12438         goto parsesub_return;
12439 }
12440
12441 /*
12442  * Called to parse command substitutions.  Newstyle is set if the command
12443  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12444  * list of commands (passed by reference), and savelen is the number of
12445  * characters on the top of the stack which must be preserved.
12446  */
12447 parsebackq: {
12448         struct nodelist **nlpp;
12449         union node *n;
12450         char *str;
12451         size_t savelen;
12452         smallint saveprompt = 0;
12453
12454         str = NULL;
12455         savelen = out - (char *)stackblock();
12456         if (savelen > 0) {
12457                 /*
12458                  * FIXME: this can allocate very large block on stack and SEGV.
12459                  * Example:
12460                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12461                  * allocates 100kb for every command subst. With about
12462                  * a hundred command substitutions stack overflows.
12463                  * With larger prepended string, SEGV happens sooner.
12464                  */
12465                 str = alloca(savelen);
12466                 memcpy(str, stackblock(), savelen);
12467         }
12468
12469         if (oldstyle) {
12470                 /* We must read until the closing backquote, giving special
12471                  * treatment to some slashes, and then push the string and
12472                  * reread it as input, interpreting it normally.
12473                  */
12474                 char *pout;
12475                 size_t psavelen;
12476                 char *pstr;
12477
12478                 STARTSTACKSTR(pout);
12479                 for (;;) {
12480                         int pc;
12481
12482                         setprompt_if(needprompt, 2);
12483                         pc = pgetc();
12484                         switch (pc) {
12485                         case '`':
12486                                 goto done;
12487
12488                         case '\\':
12489                                 pc = pgetc();
12490                                 if (pc == '\n') {
12491                                         nlprompt();
12492                                         /*
12493                                          * If eating a newline, avoid putting
12494                                          * the newline into the new character
12495                                          * stream (via the STPUTC after the
12496                                          * switch).
12497                                          */
12498                                         continue;
12499                                 }
12500                                 if (pc != '\\' && pc != '`' && pc != '$'
12501                                  && (!dblquote || pc != '"')
12502                                 ) {
12503                                         STPUTC('\\', pout);
12504                                 }
12505                                 if (pc <= 255 /* not PEOA or PEOF */) {
12506                                         break;
12507                                 }
12508                                 /* fall through */
12509
12510                         case PEOF:
12511                         IF_ASH_ALIAS(case PEOA:)
12512                                 raise_error_syntax("EOF in backquote substitution");
12513
12514                         case '\n':
12515                                 nlnoprompt();
12516                                 break;
12517
12518                         default:
12519                                 break;
12520                         }
12521                         STPUTC(pc, pout);
12522                 }
12523  done:
12524                 STPUTC('\0', pout);
12525                 psavelen = pout - (char *)stackblock();
12526                 if (psavelen > 0) {
12527                         pstr = grabstackstr(pout);
12528                         setinputstring(pstr);
12529                 }
12530         }
12531         nlpp = &bqlist;
12532         while (*nlpp)
12533                 nlpp = &(*nlpp)->next;
12534         *nlpp = stzalloc(sizeof(**nlpp));
12535         /* (*nlpp)->next = NULL; - stzalloc did it */
12536
12537         if (oldstyle) {
12538                 saveprompt = doprompt;
12539                 doprompt = 0;
12540         }
12541
12542         n = list(2);
12543
12544         if (oldstyle)
12545                 doprompt = saveprompt;
12546         else if (readtoken() != TRP)
12547                 raise_error_unexpected_syntax(TRP);
12548
12549         (*nlpp)->n = n;
12550         if (oldstyle) {
12551                 /*
12552                  * Start reading from old file again, ignoring any pushed back
12553                  * tokens left from the backquote parsing
12554                  */
12555                 popfile();
12556                 tokpushback = 0;
12557         }
12558         while (stackblocksize() <= savelen)
12559                 growstackblock();
12560         STARTSTACKSTR(out);
12561         if (str) {
12562                 memcpy(out, str, savelen);
12563                 STADJUST(savelen, out);
12564         }
12565         USTPUTC(CTLBACKQ, out);
12566         if (oldstyle)
12567                 goto parsebackq_oldreturn;
12568         goto parsebackq_newreturn;
12569 }
12570
12571 #if ENABLE_FEATURE_SH_MATH
12572 /*
12573  * Parse an arithmetic expansion (indicate start of one and set state)
12574  */
12575 parsearith: {
12576         if (++arinest == 1) {
12577                 prevsyntax = syntax;
12578                 syntax = ARISYNTAX;
12579         }
12580         USTPUTC(CTLARI, out);
12581         goto parsearith_return;
12582 }
12583 #endif
12584 } /* end of readtoken */
12585
12586 /*
12587  * Read the next input token.
12588  * If the token is a word, we set backquotelist to the list of cmds in
12589  *      backquotes.  We set quoteflag to true if any part of the word was
12590  *      quoted.
12591  * If the token is TREDIR, then we set redirnode to a structure containing
12592  *      the redirection.
12593  *
12594  * [Change comment:  here documents and internal procedures]
12595  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12596  *  word parsing code into a separate routine.  In this case, readtoken
12597  *  doesn't need to have any internal procedures, but parseword does.
12598  *  We could also make parseoperator in essence the main routine, and
12599  *  have parseword (readtoken1?) handle both words and redirection.]
12600  */
12601 #define NEW_xxreadtoken
12602 #ifdef NEW_xxreadtoken
12603 /* singles must be first! */
12604 static const char xxreadtoken_chars[7] ALIGN1 = {
12605         '\n', '(', ')', /* singles */
12606         '&', '|', ';',  /* doubles */
12607         0
12608 };
12609
12610 #define xxreadtoken_singles 3
12611 #define xxreadtoken_doubles 3
12612
12613 static const char xxreadtoken_tokens[] ALIGN1 = {
12614         TNL, TLP, TRP,          /* only single occurrence allowed */
12615         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12616         TEOF,                   /* corresponds to trailing nul */
12617         TAND, TOR, TENDCASE     /* if double occurrence */
12618 };
12619
12620 static int
12621 xxreadtoken(void)
12622 {
12623         int c;
12624
12625         if (tokpushback) {
12626                 tokpushback = 0;
12627                 return lasttoken;
12628         }
12629         setprompt_if(needprompt, 2);
12630         for (;;) {                      /* until token or start of word found */
12631                 c = pgetc();
12632                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12633                         continue;
12634
12635                 if (c == '#') {
12636                         while ((c = pgetc()) != '\n' && c != PEOF)
12637                                 continue;
12638                         pungetc();
12639                 } else if (c == '\\') {
12640                         if (pgetc() != '\n') {
12641                                 pungetc();
12642                                 break; /* return readtoken1(...) */
12643                         }
12644                         nlprompt();
12645                 } else {
12646                         const char *p;
12647
12648                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12649                         if (c != PEOF) {
12650                                 if (c == '\n') {
12651                                         nlnoprompt();
12652                                 }
12653
12654                                 p = strchr(xxreadtoken_chars, c);
12655                                 if (p == NULL)
12656                                         break; /* return readtoken1(...) */
12657
12658                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12659                                         int cc = pgetc();
12660                                         if (cc == c) {    /* double occurrence? */
12661                                                 p += xxreadtoken_doubles + 1;
12662                                         } else {
12663                                                 pungetc();
12664 #if BASH_REDIR_OUTPUT
12665                                                 if (c == '&' && cc == '>') /* &> */
12666                                                         break; /* return readtoken1(...) */
12667 #endif
12668                                         }
12669                                 }
12670                         }
12671                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12672                         return lasttoken;
12673                 }
12674         } /* for (;;) */
12675
12676         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12677 }
12678 #else /* old xxreadtoken */
12679 #define RETURN(token)   return lasttoken = token
12680 static int
12681 xxreadtoken(void)
12682 {
12683         int c;
12684
12685         if (tokpushback) {
12686                 tokpushback = 0;
12687                 return lasttoken;
12688         }
12689         setprompt_if(needprompt, 2);
12690         for (;;) {      /* until token or start of word found */
12691                 c = pgetc();
12692                 switch (c) {
12693                 case ' ': case '\t':
12694                 IF_ASH_ALIAS(case PEOA:)
12695                         continue;
12696                 case '#':
12697                         while ((c = pgetc()) != '\n' && c != PEOF)
12698                                 continue;
12699                         pungetc();
12700                         continue;
12701                 case '\\':
12702                         if (pgetc() == '\n') {
12703                                 nlprompt();
12704                                 continue;
12705                         }
12706                         pungetc();
12707                         goto breakloop;
12708                 case '\n':
12709                         nlnoprompt();
12710                         RETURN(TNL);
12711                 case PEOF:
12712                         RETURN(TEOF);
12713                 case '&':
12714                         if (pgetc() == '&')
12715                                 RETURN(TAND);
12716                         pungetc();
12717                         RETURN(TBACKGND);
12718                 case '|':
12719                         if (pgetc() == '|')
12720                                 RETURN(TOR);
12721                         pungetc();
12722                         RETURN(TPIPE);
12723                 case ';':
12724                         if (pgetc() == ';')
12725                                 RETURN(TENDCASE);
12726                         pungetc();
12727                         RETURN(TSEMI);
12728                 case '(':
12729                         RETURN(TLP);
12730                 case ')':
12731                         RETURN(TRP);
12732                 default:
12733                         goto breakloop;
12734                 }
12735         }
12736  breakloop:
12737         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12738 #undef RETURN
12739 }
12740 #endif /* old xxreadtoken */
12741
12742 static int
12743 readtoken(void)
12744 {
12745         int t;
12746         int kwd = checkkwd;
12747 #if DEBUG
12748         smallint alreadyseen = tokpushback;
12749 #endif
12750
12751 #if ENABLE_ASH_ALIAS
12752  top:
12753 #endif
12754
12755         t = xxreadtoken();
12756
12757         /*
12758          * eat newlines
12759          */
12760         if (kwd & CHKNL) {
12761                 while (t == TNL) {
12762                         parseheredoc();
12763                         t = xxreadtoken();
12764                 }
12765         }
12766
12767         if (t != TWORD || quoteflag) {
12768                 goto out;
12769         }
12770
12771         /*
12772          * check for keywords
12773          */
12774         if (kwd & CHKKWD) {
12775                 const char *const *pp;
12776
12777                 pp = findkwd(wordtext);
12778                 if (pp) {
12779                         lasttoken = t = pp - tokname_array;
12780                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12781                         goto out;
12782                 }
12783         }
12784
12785         if (checkkwd & CHKALIAS) {
12786 #if ENABLE_ASH_ALIAS
12787                 struct alias *ap;
12788                 ap = lookupalias(wordtext, 1);
12789                 if (ap != NULL) {
12790                         if (*ap->val) {
12791                                 pushstring(ap->val, ap);
12792                         }
12793                         goto top;
12794                 }
12795 #endif
12796         }
12797  out:
12798         checkkwd = 0;
12799 #if DEBUG
12800         if (!alreadyseen)
12801                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12802         else
12803                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12804 #endif
12805         return t;
12806 }
12807
12808 static int
12809 peektoken(void)
12810 {
12811         int t;
12812
12813         t = readtoken();
12814         tokpushback = 1;
12815         return t;
12816 }
12817
12818 /*
12819  * Read and parse a command.  Returns NODE_EOF on end of file.
12820  * (NULL is a valid parse tree indicating a blank line.)
12821  */
12822 static union node *
12823 parsecmd(int interact)
12824 {
12825         tokpushback = 0;
12826         checkkwd = 0;
12827         heredoclist = 0;
12828         doprompt = interact;
12829         setprompt_if(doprompt, doprompt);
12830         needprompt = 0;
12831         return list(1);
12832 }
12833
12834 /*
12835  * Input any here documents.
12836  */
12837 static void
12838 parseheredoc(void)
12839 {
12840         struct heredoc *here;
12841         union node *n;
12842
12843         here = heredoclist;
12844         heredoclist = NULL;
12845
12846         while (here) {
12847                 setprompt_if(needprompt, 2);
12848                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12849                                 here->eofmark, here->striptabs);
12850                 n = stzalloc(sizeof(struct narg));
12851                 n->narg.type = NARG;
12852                 /*n->narg.next = NULL; - stzalloc did it */
12853                 n->narg.text = wordtext;
12854                 n->narg.backquote = backquotelist;
12855                 here->here->nhere.doc = n;
12856                 here = here->next;
12857         }
12858 }
12859
12860
12861 static const char *
12862 expandstr(const char *ps, int syntax_type)
12863 {
12864         union node n;
12865         int saveprompt;
12866
12867         /* XXX Fix (char *) cast. */
12868         setinputstring((char *)ps);
12869
12870         saveprompt = doprompt;
12871         doprompt = 0;
12872
12873         /* readtoken1() might die horribly.
12874          * Try a prompt with syntactically wrong command:
12875          * PS1='$(date "+%H:%M:%S) > '
12876          */
12877         {
12878                 volatile int saveint;
12879                 struct jmploc *volatile savehandler = exception_handler;
12880                 struct jmploc jmploc;
12881                 SAVE_INT(saveint);
12882                 if (setjmp(jmploc.loc) == 0) {
12883                         exception_handler = &jmploc;
12884                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12885                 }
12886                 exception_handler = savehandler;
12887                 RESTORE_INT(saveint);
12888         }
12889
12890         doprompt = saveprompt;
12891
12892         popfile();
12893
12894         n.narg.type = NARG;
12895         n.narg.next = NULL;
12896         n.narg.text = wordtext;
12897         n.narg.backquote = backquotelist;
12898
12899         expandarg(&n, NULL, EXP_QUOTED);
12900         return stackblock();
12901 }
12902
12903 static inline int
12904 parser_eof(void)
12905 {
12906         return tokpushback && lasttoken == TEOF;
12907 }
12908
12909 /*
12910  * Execute a command or commands contained in a string.
12911  */
12912 static int
12913 evalstring(char *s, int flags)
12914 {
12915         struct jmploc *volatile savehandler;
12916         struct jmploc jmploc;
12917         int ex;
12918
12919         union node *n;
12920         struct stackmark smark;
12921         int status;
12922
12923         s = sstrdup(s);
12924         setinputstring(s);
12925         setstackmark(&smark);
12926
12927         status = 0;
12928         /* On exception inside execution loop, we must popfile().
12929          * Try interactively:
12930          *      readonly a=a
12931          *      command eval "a=b"  # throws "is read only" error
12932          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12933          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12934          */
12935         savehandler = exception_handler;
12936         ex = setjmp(jmploc.loc);
12937         if (ex)
12938                 goto out;
12939         exception_handler = &jmploc;
12940
12941         while ((n = parsecmd(0)) != NODE_EOF) {
12942                 int i;
12943
12944                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12945                 if (n)
12946                         status = i;
12947                 popstackmark(&smark);
12948                 if (evalskip)
12949                         break;
12950         }
12951  out:
12952         popstackmark(&smark);
12953         popfile();
12954         stunalloc(s);
12955
12956         exception_handler = savehandler;
12957         if (ex)
12958                 longjmp(exception_handler->loc, ex);
12959
12960         return status;
12961 }
12962
12963 /*
12964  * The eval command.
12965  */
12966 static int FAST_FUNC
12967 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12968 {
12969         char *p;
12970         char *concat;
12971
12972         if (argv[1]) {
12973                 p = argv[1];
12974                 argv += 2;
12975                 if (argv[0]) {
12976                         STARTSTACKSTR(concat);
12977                         for (;;) {
12978                                 concat = stack_putstr(p, concat);
12979                                 p = *argv++;
12980                                 if (p == NULL)
12981                                         break;
12982                                 STPUTC(' ', concat);
12983                         }
12984                         STPUTC('\0', concat);
12985                         p = grabstackstr(concat);
12986                 }
12987                 return evalstring(p, flags & EV_TESTED);
12988         }
12989         return 0;
12990 }
12991
12992 /*
12993  * Read and execute commands.
12994  * "Top" is nonzero for the top level command loop;
12995  * it turns on prompting if the shell is interactive.
12996  */
12997 static int
12998 cmdloop(int top)
12999 {
13000         union node *n;
13001         struct stackmark smark;
13002         int inter;
13003         int status = 0;
13004         int numeof = 0;
13005
13006         TRACE(("cmdloop(%d) called\n", top));
13007         for (;;) {
13008                 int skip;
13009
13010                 setstackmark(&smark);
13011 #if JOBS
13012                 if (doing_jobctl)
13013                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13014 #endif
13015                 inter = 0;
13016                 if (iflag && top) {
13017                         inter++;
13018                         chkmail();
13019                 }
13020                 n = parsecmd(inter);
13021 #if DEBUG
13022                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13023                         showtree(n);
13024 #endif
13025                 if (n == NODE_EOF) {
13026                         if (!top || numeof >= 50)
13027                                 break;
13028                         if (!stoppedjobs()) {
13029                                 if (!Iflag)
13030                                         break;
13031                                 out2str("\nUse \"exit\" to leave shell.\n");
13032                         }
13033                         numeof++;
13034                 } else if (nflag == 0) {
13035                         int i;
13036
13037                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13038                         job_warning >>= 1;
13039                         numeof = 0;
13040                         i = evaltree(n, 0);
13041                         if (n)
13042                                 status = i;
13043                 }
13044                 popstackmark(&smark);
13045                 skip = evalskip;
13046
13047                 if (skip) {
13048                         evalskip &= ~SKIPFUNC;
13049                         break;
13050                 }
13051         }
13052         return status;
13053 }
13054
13055 /*
13056  * Take commands from a file.  To be compatible we should do a path
13057  * search for the file, which is necessary to find sub-commands.
13058  */
13059 static char *
13060 find_dot_file(char *name)
13061 {
13062         char *fullname;
13063         const char *path = pathval();
13064         struct stat statb;
13065
13066         /* don't try this for absolute or relative paths */
13067         if (strchr(name, '/'))
13068                 return name;
13069
13070         while ((fullname = path_advance(&path, name)) != NULL) {
13071                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13072                         /*
13073                          * Don't bother freeing here, since it will
13074                          * be freed by the caller.
13075                          */
13076                         return fullname;
13077                 }
13078                 if (fullname != name)
13079                         stunalloc(fullname);
13080         }
13081         /* not found in PATH */
13082
13083 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13084         return name;
13085 #else
13086         ash_msg_and_raise_error("%s: not found", name);
13087         /* NOTREACHED */
13088 #endif
13089 }
13090
13091 static int FAST_FUNC
13092 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13093 {
13094         /* "false; . empty_file; echo $?" should print 0, not 1: */
13095         int status = 0;
13096         char *fullname;
13097         char **argv;
13098         char *args_need_save;
13099         volatile struct shparam saveparam;
13100
13101 //???
13102 //      struct strlist *sp;
13103 //      for (sp = cmdenviron; sp; sp = sp->next)
13104 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13105
13106         nextopt(nullstr); /* handle possible "--" */
13107         argv = argptr;
13108
13109         if (!argv[0]) {
13110                 /* bash says: "bash: .: filename argument required" */
13111                 return 2; /* bash compat */
13112         }
13113
13114         /* This aborts if file isn't found, which is POSIXly correct.
13115          * bash returns exitcode 1 instead.
13116          */
13117         fullname = find_dot_file(argv[0]);
13118         argv++;
13119         args_need_save = argv[0];
13120         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13121                 int argc;
13122                 saveparam = shellparam;
13123                 shellparam.malloced = 0;
13124                 argc = 1;
13125                 while (argv[argc])
13126                         argc++;
13127                 shellparam.nparam = argc;
13128                 shellparam.p = argv;
13129         };
13130
13131         /* This aborts if file can't be opened, which is POSIXly correct.
13132          * bash returns exitcode 1 instead.
13133          */
13134         setinputfile(fullname, INPUT_PUSH_FILE);
13135         commandname = fullname;
13136         status = cmdloop(0);
13137         popfile();
13138
13139         if (args_need_save) {
13140                 freeparam(&shellparam);
13141                 shellparam = saveparam;
13142         };
13143
13144         return status;
13145 }
13146
13147 static int FAST_FUNC
13148 exitcmd(int argc UNUSED_PARAM, char **argv)
13149 {
13150         if (stoppedjobs())
13151                 return 0;
13152         if (argv[1])
13153                 exitstatus = number(argv[1]);
13154         raise_exception(EXEXIT);
13155         /* NOTREACHED */
13156 }
13157
13158 /*
13159  * Read a file containing shell functions.
13160  */
13161 static void
13162 readcmdfile(char *name)
13163 {
13164         setinputfile(name, INPUT_PUSH_FILE);
13165         cmdloop(0);
13166         popfile();
13167 }
13168
13169
13170 /* ============ find_command inplementation */
13171
13172 /*
13173  * Resolve a command name.  If you change this routine, you may have to
13174  * change the shellexec routine as well.
13175  */
13176 static void
13177 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13178 {
13179         struct tblentry *cmdp;
13180         int idx;
13181         int prev;
13182         char *fullname;
13183         struct stat statb;
13184         int e;
13185         int updatetbl;
13186         struct builtincmd *bcmd;
13187
13188         /* If name contains a slash, don't use PATH or hash table */
13189         if (strchr(name, '/') != NULL) {
13190                 entry->u.index = -1;
13191                 if (act & DO_ABS) {
13192                         while (stat(name, &statb) < 0) {
13193 #ifdef SYSV
13194                                 if (errno == EINTR)
13195                                         continue;
13196 #endif
13197                                 entry->cmdtype = CMDUNKNOWN;
13198                                 return;
13199                         }
13200                 }
13201                 entry->cmdtype = CMDNORMAL;
13202                 return;
13203         }
13204
13205 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13206
13207         updatetbl = (path == pathval());
13208         if (!updatetbl) {
13209                 act |= DO_ALTPATH;
13210                 if (strstr(path, "%builtin") != NULL)
13211                         act |= DO_ALTBLTIN;
13212         }
13213
13214         /* If name is in the table, check answer will be ok */
13215         cmdp = cmdlookup(name, 0);
13216         if (cmdp != NULL) {
13217                 int bit;
13218
13219                 switch (cmdp->cmdtype) {
13220                 default:
13221 #if DEBUG
13222                         abort();
13223 #endif
13224                 case CMDNORMAL:
13225                         bit = DO_ALTPATH;
13226                         break;
13227                 case CMDFUNCTION:
13228                         bit = DO_NOFUNC;
13229                         break;
13230                 case CMDBUILTIN:
13231                         bit = DO_ALTBLTIN;
13232                         break;
13233                 }
13234                 if (act & bit) {
13235                         updatetbl = 0;
13236                         cmdp = NULL;
13237                 } else if (cmdp->rehash == 0)
13238                         /* if not invalidated by cd, we're done */
13239                         goto success;
13240         }
13241
13242         /* If %builtin not in path, check for builtin next */
13243         bcmd = find_builtin(name);
13244         if (bcmd) {
13245                 if (IS_BUILTIN_REGULAR(bcmd))
13246                         goto builtin_success;
13247                 if (act & DO_ALTPATH) {
13248                         if (!(act & DO_ALTBLTIN))
13249                                 goto builtin_success;
13250                 } else if (builtinloc <= 0) {
13251                         goto builtin_success;
13252                 }
13253         }
13254
13255 #if ENABLE_FEATURE_SH_STANDALONE
13256         {
13257                 int applet_no = find_applet_by_name(name);
13258                 if (applet_no >= 0) {
13259                         entry->cmdtype = CMDNORMAL;
13260                         entry->u.index = -2 - applet_no;
13261                         return;
13262                 }
13263         }
13264 #endif
13265
13266         /* We have to search path. */
13267         prev = -1;              /* where to start */
13268         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13269                 if (cmdp->cmdtype == CMDBUILTIN)
13270                         prev = builtinloc;
13271                 else
13272                         prev = cmdp->param.index;
13273         }
13274
13275         e = ENOENT;
13276         idx = -1;
13277  loop:
13278         while ((fullname = path_advance(&path, name)) != NULL) {
13279                 stunalloc(fullname);
13280                 /* NB: code below will still use fullname
13281                  * despite it being "unallocated" */
13282                 idx++;
13283                 if (pathopt) {
13284                         if (prefix(pathopt, "builtin")) {
13285                                 if (bcmd)
13286                                         goto builtin_success;
13287                                 continue;
13288                         }
13289                         if ((act & DO_NOFUNC)
13290                          || !prefix(pathopt, "func")
13291                         ) {     /* ignore unimplemented options */
13292                                 continue;
13293                         }
13294                 }
13295                 /* if rehash, don't redo absolute path names */
13296                 if (fullname[0] == '/' && idx <= prev) {
13297                         if (idx < prev)
13298                                 continue;
13299                         TRACE(("searchexec \"%s\": no change\n", name));
13300                         goto success;
13301                 }
13302                 while (stat(fullname, &statb) < 0) {
13303 #ifdef SYSV
13304                         if (errno == EINTR)
13305                                 continue;
13306 #endif
13307                         if (errno != ENOENT && errno != ENOTDIR)
13308                                 e = errno;
13309                         goto loop;
13310                 }
13311                 e = EACCES;     /* if we fail, this will be the error */
13312                 if (!S_ISREG(statb.st_mode))
13313                         continue;
13314                 if (pathopt) {          /* this is a %func directory */
13315                         stalloc(strlen(fullname) + 1);
13316                         /* NB: stalloc will return space pointed by fullname
13317                          * (because we don't have any intervening allocations
13318                          * between stunalloc above and this stalloc) */
13319                         readcmdfile(fullname);
13320                         cmdp = cmdlookup(name, 0);
13321                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13322                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13323                         stunalloc(fullname);
13324                         goto success;
13325                 }
13326                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13327                 if (!updatetbl) {
13328                         entry->cmdtype = CMDNORMAL;
13329                         entry->u.index = idx;
13330                         return;
13331                 }
13332                 INT_OFF;
13333                 cmdp = cmdlookup(name, 1);
13334                 cmdp->cmdtype = CMDNORMAL;
13335                 cmdp->param.index = idx;
13336                 INT_ON;
13337                 goto success;
13338         }
13339
13340         /* We failed.  If there was an entry for this command, delete it */
13341         if (cmdp && updatetbl)
13342                 delete_cmd_entry();
13343         if (act & DO_ERR) {
13344 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13345                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13346                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13347                         char *argv[3];
13348                         argv[0] = (char*) "command_not_found_handle";
13349                         argv[1] = name;
13350                         argv[2] = NULL;
13351                         evalfun(hookp->param.func, 2, argv, 0);
13352                         entry->cmdtype = CMDUNKNOWN;
13353                         return;
13354                 }
13355 #endif
13356                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13357         }
13358         entry->cmdtype = CMDUNKNOWN;
13359         return;
13360
13361  builtin_success:
13362         if (!updatetbl) {
13363                 entry->cmdtype = CMDBUILTIN;
13364                 entry->u.cmd = bcmd;
13365                 return;
13366         }
13367         INT_OFF;
13368         cmdp = cmdlookup(name, 1);
13369         cmdp->cmdtype = CMDBUILTIN;
13370         cmdp->param.cmd = bcmd;
13371         INT_ON;
13372  success:
13373         cmdp->rehash = 0;
13374         entry->cmdtype = cmdp->cmdtype;
13375         entry->u = cmdp->param;
13376 }
13377
13378
13379 /*
13380  * The trap builtin.
13381  */
13382 static int FAST_FUNC
13383 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13384 {
13385         char *action;
13386         char **ap;
13387         int signo, exitcode;
13388
13389         nextopt(nullstr);
13390         ap = argptr;
13391         if (!*ap) {
13392                 for (signo = 0; signo < NSIG; signo++) {
13393                         char *tr = trap_ptr[signo];
13394                         if (tr) {
13395                                 /* note: bash adds "SIG", but only if invoked
13396                                  * as "bash". If called as "sh", or if set -o posix,
13397                                  * then it prints short signal names.
13398                                  * We are printing short names: */
13399                                 out1fmt("trap -- %s %s\n",
13400                                                 single_quote(tr),
13401                                                 get_signame(signo));
13402                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13403                  * In this case, we will exit very soon, no need to free(). */
13404                                 /* if (trap_ptr != trap && tp[0]) */
13405                                 /*      free(tr); */
13406                         }
13407                 }
13408                 /*
13409                 if (trap_ptr != trap) {
13410                         free(trap_ptr);
13411                         trap_ptr = trap;
13412                 }
13413                 */
13414                 return 0;
13415         }
13416
13417         /* Why the second check?
13418          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13419          * In this case, NUM is signal no, not an action.
13420          */
13421         action = NULL;
13422         if (ap[1] && !is_number(ap[0]))
13423                 action = *ap++;
13424
13425         exitcode = 0;
13426         while (*ap) {
13427                 signo = get_signum(*ap);
13428                 if (signo < 0) {
13429                         /* Mimic bash message exactly */
13430                         ash_msg("%s: invalid signal specification", *ap);
13431                         exitcode = 1;
13432                         goto next;
13433                 }
13434                 INT_OFF;
13435                 if (action) {
13436                         if (LONE_DASH(action))
13437                                 action = NULL;
13438                         else {
13439                                 if (action[0]) /* not NULL and not "" and not "-" */
13440                                         may_have_traps = 1;
13441                                 action = ckstrdup(action);
13442                         }
13443                 }
13444                 free(trap[signo]);
13445                 trap[signo] = action;
13446                 if (signo != 0)
13447                         setsignal(signo);
13448                 INT_ON;
13449  next:
13450                 ap++;
13451         }
13452         return exitcode;
13453 }
13454
13455
13456 /* ============ Builtins */
13457
13458 #if ENABLE_ASH_HELP
13459 static int FAST_FUNC
13460 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13461 {
13462         unsigned col;
13463         unsigned i;
13464
13465         out1fmt(
13466                 "Built-in commands:\n"
13467                 "------------------\n");
13468         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13469                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13470                                         builtintab[i].name + 1);
13471                 if (col > 60) {
13472                         out1fmt("\n");
13473                         col = 0;
13474                 }
13475         }
13476 # if ENABLE_FEATURE_SH_STANDALONE
13477         {
13478                 const char *a = applet_names;
13479                 while (*a) {
13480                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13481                         if (col > 60) {
13482                                 out1fmt("\n");
13483                                 col = 0;
13484                         }
13485                         while (*a++ != '\0')
13486                                 continue;
13487                 }
13488         }
13489 # endif
13490         newline_and_flush(stdout);
13491         return EXIT_SUCCESS;
13492 }
13493 #endif
13494
13495 #if MAX_HISTORY
13496 static int FAST_FUNC
13497 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13498 {
13499         show_history(line_input_state);
13500         return EXIT_SUCCESS;
13501 }
13502 #endif
13503
13504 /*
13505  * The export and readonly commands.
13506  */
13507 static int FAST_FUNC
13508 exportcmd(int argc UNUSED_PARAM, char **argv)
13509 {
13510         struct var *vp;
13511         char *name;
13512         const char *p;
13513         char **aptr;
13514         char opt;
13515         int flag;
13516         int flag_off;
13517
13518         /* "readonly" in bash accepts, but ignores -n.
13519          * We do the same: it saves a conditional in nextopt's param.
13520          */
13521         flag_off = 0;
13522         while ((opt = nextopt("np")) != '\0') {
13523                 if (opt == 'n')
13524                         flag_off = VEXPORT;
13525         }
13526         flag = VEXPORT;
13527         if (argv[0][0] == 'r') {
13528                 flag = VREADONLY;
13529                 flag_off = 0; /* readonly ignores -n */
13530         }
13531         flag_off = ~flag_off;
13532
13533         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13534         {
13535                 aptr = argptr;
13536                 name = *aptr;
13537                 if (name) {
13538                         do {
13539                                 p = strchr(name, '=');
13540                                 if (p != NULL) {
13541                                         p++;
13542                                 } else {
13543                                         vp = *findvar(hashvar(name), name);
13544                                         if (vp) {
13545                                                 vp->flags = ((vp->flags | flag) & flag_off);
13546                                                 continue;
13547                                         }
13548                                 }
13549                                 setvar(name, p, (flag & flag_off));
13550                         } while ((name = *++aptr) != NULL);
13551                         return 0;
13552                 }
13553         }
13554
13555         /* No arguments. Show the list of exported or readonly vars.
13556          * -n is ignored.
13557          */
13558         showvars(argv[0], flag, 0);
13559         return 0;
13560 }
13561
13562 /*
13563  * Delete a function if it exists.
13564  */
13565 static void
13566 unsetfunc(const char *name)
13567 {
13568         struct tblentry *cmdp;
13569
13570         cmdp = cmdlookup(name, 0);
13571         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13572                 delete_cmd_entry();
13573 }
13574
13575 /*
13576  * The unset builtin command.  We unset the function before we unset the
13577  * variable to allow a function to be unset when there is a readonly variable
13578  * with the same name.
13579  */
13580 static int FAST_FUNC
13581 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13582 {
13583         char **ap;
13584         int i;
13585         int flag = 0;
13586
13587         while ((i = nextopt("vf")) != 0) {
13588                 flag = i;
13589         }
13590
13591         for (ap = argptr; *ap; ap++) {
13592                 if (flag != 'f') {
13593                         unsetvar(*ap);
13594                         continue;
13595                 }
13596                 if (flag != 'v')
13597                         unsetfunc(*ap);
13598         }
13599         return 0;
13600 }
13601
13602 static const unsigned char timescmd_str[] ALIGN1 = {
13603         ' ',  offsetof(struct tms, tms_utime),
13604         '\n', offsetof(struct tms, tms_stime),
13605         ' ',  offsetof(struct tms, tms_cutime),
13606         '\n', offsetof(struct tms, tms_cstime),
13607         0
13608 };
13609 static int FAST_FUNC
13610 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13611 {
13612         unsigned clk_tck;
13613         const unsigned char *p;
13614         struct tms buf;
13615
13616         clk_tck = bb_clk_tck();
13617
13618         times(&buf);
13619         p = timescmd_str;
13620         do {
13621                 unsigned sec, frac;
13622                 unsigned long t;
13623                 t = *(clock_t *)(((char *) &buf) + p[1]);
13624                 sec = t / clk_tck;
13625                 frac = t % clk_tck;
13626                 out1fmt("%um%u.%03us%c",
13627                         sec / 60, sec % 60,
13628                         (frac * 1000) / clk_tck,
13629                         p[0]);
13630                 p += 2;
13631         } while (*p);
13632
13633         return 0;
13634 }
13635
13636 #if ENABLE_FEATURE_SH_MATH
13637 /*
13638  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13639  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13640  *
13641  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13642  */
13643 static int FAST_FUNC
13644 letcmd(int argc UNUSED_PARAM, char **argv)
13645 {
13646         arith_t i;
13647
13648         argv++;
13649         if (!*argv)
13650                 ash_msg_and_raise_error("expression expected");
13651         do {
13652                 i = ash_arith(*argv);
13653         } while (*++argv);
13654
13655         return !i;
13656 }
13657 #endif
13658
13659 /*
13660  * The read builtin. Options:
13661  *      -r              Do not interpret '\' specially
13662  *      -s              Turn off echo (tty only)
13663  *      -n NCHARS       Read NCHARS max
13664  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13665  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13666  *      -u FD           Read from given FD instead of fd 0
13667  *      -d DELIM        End on DELIM char, not newline
13668  * This uses unbuffered input, which may be avoidable in some cases.
13669  * TODO: bash also has:
13670  *      -a ARRAY        Read into array[0],[1],etc
13671  *      -e              Use line editing (tty only)
13672  */
13673 static int FAST_FUNC
13674 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13675 {
13676         char *opt_n = NULL;
13677         char *opt_p = NULL;
13678         char *opt_t = NULL;
13679         char *opt_u = NULL;
13680         char *opt_d = NULL; /* optimized out if !BASH */
13681         int read_flags = 0;
13682         const char *r;
13683         int i;
13684
13685         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13686                 switch (i) {
13687                 case 'p':
13688                         opt_p = optionarg;
13689                         break;
13690                 case 'n':
13691                         opt_n = optionarg;
13692                         break;
13693                 case 's':
13694                         read_flags |= BUILTIN_READ_SILENT;
13695                         break;
13696                 case 't':
13697                         opt_t = optionarg;
13698                         break;
13699                 case 'r':
13700                         read_flags |= BUILTIN_READ_RAW;
13701                         break;
13702                 case 'u':
13703                         opt_u = optionarg;
13704                         break;
13705 #if BASH_READ_D
13706                 case 'd':
13707                         opt_d = optionarg;
13708                         break;
13709 #endif
13710                 default:
13711                         break;
13712                 }
13713         }
13714
13715         /* "read -s" needs to save/restore termios, can't allow ^C
13716          * to jump out of it.
13717          */
13718  again:
13719         INT_OFF;
13720         r = shell_builtin_read(setvar0,
13721                 argptr,
13722                 bltinlookup("IFS"), /* can be NULL */
13723                 read_flags,
13724                 opt_n,
13725                 opt_p,
13726                 opt_t,
13727                 opt_u,
13728                 opt_d
13729         );
13730         INT_ON;
13731
13732         if ((uintptr_t)r == 1 && errno == EINTR) {
13733                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13734                  * Correct behavior is to not exit "read"
13735                  */
13736                 if (pending_sig == 0)
13737                         goto again;
13738         }
13739
13740         if ((uintptr_t)r > 1)
13741                 ash_msg_and_raise_error(r);
13742
13743         return (uintptr_t)r;
13744 }
13745
13746 static int FAST_FUNC
13747 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13748 {
13749         static const char permuser[3] ALIGN1 = "ogu";
13750
13751         mode_t mask;
13752         int symbolic_mode = 0;
13753
13754         while (nextopt("S") != '\0') {
13755                 symbolic_mode = 1;
13756         }
13757
13758         INT_OFF;
13759         mask = umask(0);
13760         umask(mask);
13761         INT_ON;
13762
13763         if (*argptr == NULL) {
13764                 if (symbolic_mode) {
13765                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13766                         char *p = buf;
13767                         int i;
13768
13769                         i = 2;
13770                         for (;;) {
13771                                 *p++ = ',';
13772                                 *p++ = permuser[i];
13773                                 *p++ = '=';
13774                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13775                                 if (!(mask & 0400)) *p++ = 'r';
13776                                 if (!(mask & 0200)) *p++ = 'w';
13777                                 if (!(mask & 0100)) *p++ = 'x';
13778                                 mask <<= 3;
13779                                 if (--i < 0)
13780                                         break;
13781                         }
13782                         *p = '\0';
13783                         puts(buf + 1);
13784                 } else {
13785                         out1fmt("%04o\n", mask);
13786                 }
13787         } else {
13788                 char *modestr = *argptr;
13789                 /* numeric umasks are taken as-is */
13790                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13791                 if (!isdigit(modestr[0]))
13792                         mask ^= 0777;
13793                 mask = bb_parse_mode(modestr, mask);
13794                 if ((unsigned)mask > 0777) {
13795                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13796                 }
13797                 if (!isdigit(modestr[0]))
13798                         mask ^= 0777;
13799                 umask(mask);
13800         }
13801         return 0;
13802 }
13803
13804 static int FAST_FUNC
13805 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13806 {
13807         return shell_builtin_ulimit(argv);
13808 }
13809
13810 /* ============ main() and helpers */
13811
13812 /*
13813  * Called to exit the shell.
13814  */
13815 static void
13816 exitshell(void)
13817 {
13818         struct jmploc loc;
13819         char *p;
13820         int status;
13821
13822 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13823         save_history(line_input_state);
13824 #endif
13825         status = exitstatus;
13826         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13827         if (setjmp(loc.loc)) {
13828                 if (exception_type == EXEXIT)
13829                         status = exitstatus;
13830                 goto out;
13831         }
13832         exception_handler = &loc;
13833         p = trap[0];
13834         if (p) {
13835                 trap[0] = NULL;
13836                 evalskip = 0;
13837                 evalstring(p, 0);
13838                 /*free(p); - we'll exit soon */
13839         }
13840  out:
13841         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13842          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13843          */
13844         setjobctl(0);
13845         flush_stdout_stderr();
13846         _exit(status);
13847         /* NOTREACHED */
13848 }
13849
13850 /* Don't inline: conserve stack of caller from having our locals too */
13851 static NOINLINE void
13852 init(void)
13853 {
13854         /* we will never free this */
13855         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13856         basepf.linno = 1;
13857
13858         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13859         setsignal(SIGCHLD);
13860
13861         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13862          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13863          */
13864         signal(SIGHUP, SIG_DFL);
13865
13866         {
13867                 char **envp;
13868                 const char *p;
13869
13870                 initvar();
13871                 for (envp = environ; envp && *envp; envp++) {
13872 /* Used to have
13873  *                      p = endofname(*envp);
13874  *                      if (p != *envp && *p == '=') {
13875  * here to weed out badly-named variables, but this breaks
13876  * scenarios where people do want them passed to children:
13877  * import os
13878  * os.environ["test-test"]="test"
13879  * if os.fork() == 0:
13880  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13881  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13882  */
13883                         if (strchr(*envp, '=')) {
13884                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13885                         }
13886                 }
13887
13888                 setvareq((char*)defoptindvar, VTEXTFIXED);
13889
13890                 setvar0("PPID", utoa(getppid()));
13891 #if BASH_SHLVL_VAR
13892                 p = lookupvar("SHLVL");
13893                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13894 #endif
13895 #if BASH_HOSTNAME_VAR
13896                 if (!lookupvar("HOSTNAME")) {
13897                         struct utsname uts;
13898                         uname(&uts);
13899                         setvar0("HOSTNAME", uts.nodename);
13900                 }
13901 #endif
13902                 p = lookupvar("PWD");
13903                 if (p) {
13904                         struct stat st1, st2;
13905                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13906                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13907                         ) {
13908                                 p = NULL;
13909                         }
13910                 }
13911                 setpwd(p, 0);
13912         }
13913 }
13914
13915
13916 //usage:#define ash_trivial_usage
13917 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13918 //usage:#define ash_full_usage "\n\n"
13919 //usage:        "Unix shell interpreter"
13920
13921 /*
13922  * Process the shell command line arguments.
13923  */
13924 static int
13925 procargs(char **argv)
13926 {
13927         int i;
13928         const char *xminusc;
13929         char **xargv;
13930         int login_sh;
13931
13932         xargv = argv;
13933         login_sh = xargv[0] && xargv[0][0] == '-';
13934         arg0 = xargv[0];
13935         /* if (xargv[0]) - mmm, this is always true! */
13936                 xargv++;
13937         for (i = 0; i < NOPTS; i++)
13938                 optlist[i] = 2;
13939         argptr = xargv;
13940         if (options(/*cmdline:*/ 1, &login_sh)) {
13941                 /* it already printed err message */
13942                 raise_exception(EXERROR);
13943         }
13944         xargv = argptr;
13945         xminusc = minusc;
13946         if (*xargv == NULL) {
13947                 if (xminusc)
13948                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13949                 sflag = 1;
13950         }
13951         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13952                 iflag = 1;
13953         if (mflag == 2)
13954                 mflag = iflag;
13955         for (i = 0; i < NOPTS; i++)
13956                 if (optlist[i] == 2)
13957                         optlist[i] = 0;
13958 #if DEBUG == 2
13959         debug = 1;
13960 #endif
13961         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13962         if (xminusc) {
13963                 minusc = *xargv++;
13964                 if (*xargv)
13965                         goto setarg0;
13966         } else if (!sflag) {
13967                 setinputfile(*xargv, 0);
13968  setarg0:
13969                 arg0 = *xargv++;
13970                 commandname = arg0;
13971         }
13972
13973         shellparam.p = xargv;
13974 #if ENABLE_ASH_GETOPTS
13975         shellparam.optind = 1;
13976         shellparam.optoff = -1;
13977 #endif
13978         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13979         while (*xargv) {
13980                 shellparam.nparam++;
13981                 xargv++;
13982         }
13983         optschanged();
13984
13985         return login_sh;
13986 }
13987
13988 /*
13989  * Read /etc/profile, ~/.profile, $ENV.
13990  */
13991 static void
13992 read_profile(const char *name)
13993 {
13994         name = expandstr(name, DQSYNTAX);
13995         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13996                 return;
13997         cmdloop(0);
13998         popfile();
13999 }
14000
14001 /*
14002  * This routine is called when an error or an interrupt occurs in an
14003  * interactive shell and control is returned to the main command loop.
14004  * (In dash, this function is auto-generated by build machinery).
14005  */
14006 static void
14007 reset(void)
14008 {
14009         /* from eval.c: */
14010         evalskip = 0;
14011         loopnest = 0;
14012
14013         /* from expand.c: */
14014         ifsfree();
14015
14016         /* from input.c: */
14017         g_parsefile->left_in_buffer = 0;
14018         g_parsefile->left_in_line = 0;      /* clear input buffer */
14019         popallfiles();
14020
14021         /* from redir.c: */
14022         unwindredir(NULL);
14023
14024         /* from var.c: */
14025         unwindlocalvars(NULL);
14026 }
14027
14028 #if PROFILE
14029 static short profile_buf[16384];
14030 extern int etext();
14031 #endif
14032
14033 /*
14034  * Main routine.  We initialize things, parse the arguments, execute
14035  * profiles if we're a login shell, and then call cmdloop to execute
14036  * commands.  The setjmp call sets up the location to jump to when an
14037  * exception occurs.  When an exception occurs the variable "state"
14038  * is used to figure out how far we had gotten.
14039  */
14040 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14041 int ash_main(int argc UNUSED_PARAM, char **argv)
14042 {
14043         volatile smallint state;
14044         struct jmploc jmploc;
14045         struct stackmark smark;
14046         int login_sh;
14047
14048         /* Initialize global data */
14049         INIT_G_misc();
14050         INIT_G_memstack();
14051         INIT_G_var();
14052 #if ENABLE_ASH_ALIAS
14053         INIT_G_alias();
14054 #endif
14055         INIT_G_cmdtable();
14056
14057 #if PROFILE
14058         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14059 #endif
14060
14061 #if ENABLE_FEATURE_EDITING
14062         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14063 #endif
14064         state = 0;
14065         if (setjmp(jmploc.loc)) {
14066                 smallint e;
14067                 smallint s;
14068
14069                 reset();
14070
14071                 e = exception_type;
14072                 s = state;
14073                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14074                         exitshell();
14075                 }
14076                 if (e == EXINT) {
14077                         newline_and_flush(stderr);
14078                 }
14079
14080                 popstackmark(&smark);
14081                 FORCE_INT_ON; /* enable interrupts */
14082                 if (s == 1)
14083                         goto state1;
14084                 if (s == 2)
14085                         goto state2;
14086                 if (s == 3)
14087                         goto state3;
14088                 goto state4;
14089         }
14090         exception_handler = &jmploc;
14091         rootpid = getpid();
14092
14093         init();
14094         setstackmark(&smark);
14095         login_sh = procargs(argv);
14096 #if DEBUG
14097         TRACE(("Shell args: "));
14098         trace_puts_args(argv);
14099 #endif
14100
14101         if (login_sh) {
14102                 const char *hp;
14103
14104                 state = 1;
14105                 read_profile("/etc/profile");
14106  state1:
14107                 state = 2;
14108                 hp = lookupvar("HOME");
14109                 if (hp)
14110                         read_profile("$HOME/.profile");
14111         }
14112  state2:
14113         state = 3;
14114         if (
14115 #ifndef linux
14116          getuid() == geteuid() && getgid() == getegid() &&
14117 #endif
14118          iflag
14119         ) {
14120                 const char *shinit = lookupvar("ENV");
14121                 if (shinit != NULL && *shinit != '\0')
14122                         read_profile(shinit);
14123         }
14124         popstackmark(&smark);
14125  state3:
14126         state = 4;
14127         if (minusc) {
14128                 /* evalstring pushes parsefile stack.
14129                  * Ensure we don't falsely claim that 0 (stdin)
14130                  * is one of stacked source fds.
14131                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14132                 // if (!sflag) g_parsefile->pf_fd = -1;
14133                 // ^^ not necessary since now we special-case fd 0
14134                 // in save_fd_on_redirect()
14135                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14136         }
14137
14138         if (sflag || minusc == NULL) {
14139 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14140                 if (iflag) {
14141                         const char *hp = lookupvar("HISTFILE");
14142                         if (!hp) {
14143                                 hp = lookupvar("HOME");
14144                                 if (hp) {
14145                                         INT_OFF;
14146                                         hp = concat_path_file(hp, ".ash_history");
14147                                         setvar0("HISTFILE", hp);
14148                                         free((char*)hp);
14149                                         INT_ON;
14150                                         hp = lookupvar("HISTFILE");
14151                                 }
14152                         }
14153                         if (hp)
14154                                 line_input_state->hist_file = hp;
14155 # if ENABLE_FEATURE_SH_HISTFILESIZE
14156                         hp = lookupvar("HISTFILESIZE");
14157                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14158 # endif
14159                 }
14160 #endif
14161  state4: /* XXX ??? - why isn't this before the "if" statement */
14162                 cmdloop(1);
14163         }
14164 #if PROFILE
14165         monitor(0);
14166 #endif
14167 #ifdef GPROF
14168         {
14169                 extern void _mcleanup(void);
14170                 _mcleanup();
14171         }
14172 #endif
14173         TRACE(("End of main reached\n"));
14174         exitshell();
14175         /* NOTREACHED */
14176 }
14177
14178
14179 /*-
14180  * Copyright (c) 1989, 1991, 1993, 1994
14181  *      The Regents of the University of California.  All rights reserved.
14182  *
14183  * This code is derived from software contributed to Berkeley by
14184  * Kenneth Almquist.
14185  *
14186  * Redistribution and use in source and binary forms, with or without
14187  * modification, are permitted provided that the following conditions
14188  * are met:
14189  * 1. Redistributions of source code must retain the above copyright
14190  *    notice, this list of conditions and the following disclaimer.
14191  * 2. Redistributions in binary form must reproduce the above copyright
14192  *    notice, this list of conditions and the following disclaimer in the
14193  *    documentation and/or other materials provided with the distribution.
14194  * 3. Neither the name of the University nor the names of its contributors
14195  *    may be used to endorse or promote products derived from this software
14196  *    without specific prior written permission.
14197  *
14198  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14199  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14200  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14201  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14202  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14203  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14204  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14205  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14206  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14207  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14208  * SUCH DAMAGE.
14209  */